/*
 *Copyright © 2019 mxreality.js authors
 *Website:www.mxreality.cn
 *免费软件，请保留版权注释
 */

 (function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
        typeof define === 'function' && define.amd ? define(['exports'], factory) :
            (factory(global));
}(this, (function (exports) {
    var VR = function (scene, renderer, container, cameraPara, cameraPosition) {
        this.scene = scene;
        this.renderer = renderer;
        this.container = container;
        AVR.initDomStyle(container);
        AVR.setCameraPara(this, cameraPara, cameraPosition);
        this.vrbox = {
            "radius": 2,
            "widthSegments": 180,
            "heightSegments": 180,
            "width": 2,
            "height": 2,
            "depth": 2
        };
        this.liveSettings = {
            "forceUseHls": false,
            "forceUseVndAppleMpegUrl": false,
            "forceUseXmpegUrl": false,
            "usePlugin": false,
            "loadPlugin": function (video) {
                console.log('load video', video);
            }
        }
        this.hlsConfig = {
            autoStartLoad: true,
        };
        this.flvConfig = {
            type: 'flv',
            isLive: true,
        };
        this.destoryed = false;
        this.video = null;
        this.audio = null;
        this.toolBar = null;
        this.clock = new THREE.Clock();
        this.VRObject = new THREE.Object3D();
        this.defaultAutoHideLeftTime = 3;
        this.defaultVoiceHideLeftTime = 2;
        this.defaultVolume = 0.3;
        this.sliceSegment = 0;
        this._controlTarget = new THREE.Vector3(0, 0, 0.0001);
        this._cubeCameraTimes = 0.96;
        this.playCfg = {
            muted: false,
            autoplay: false,
        };
        this.resType = {
            "video": "video",
            "box": "box",
            "slice": "slice",
            "sliceVideo": "sliceVideo",
            'flvVideo': 'flvVideo'
        };
        this.videoPlayHook = function () {
            console.log('video play')
        }
        this.videoPauseHook = function () {
            console.log('video pause')
        }
        this.asteroidConfig = {
            enable: false,
            asteroidFPS: 10,
            asteroidFov: 135,
            asteroidForwardTime: 2600,
            asteroidWaitTime: 2000,
            asteroidDepressionRate: 0.5,
            asteroidTop: 1,
            cubeResolution: 2048,
            rotationAngleOfZ: 0
        };
        this.VRhint = "请取消屏幕翻转锁定后横屏";
        this.camera = new THREE.PerspectiveCamera(this.cameraPara.fov, this.cameraPara.aspect, this.cameraPara.near, this.cameraPara.far);
        this.camera.lookAt(this._controlTarget);
        this.cameraEvt = {
            'controlGroup': function () { },
            'updatePosition': function () { },
            'hover': function () { },
            'leave': function () { }
        };
        this._takeScreenShot = false;
        this.timerList = {};
        this.camera.position.set(this.cameraPosition.x, this.cameraPosition.y, this.cameraPosition.z);
        this.loadProgressManager = new THREE.LoadingManager(function (xhr) {
            console.log("loaded");
        }, function (item, loaded, total) {
            console.log("item=", item, "loaded", loaded, "total=", total);
        }, function (xhr, cl) {
            console.log(xhr, cl);
        });
        this.scene.add(this.camera);
        this.scene.add(this.VRObject);
        //this.renderer.setPixelRatio( window.devicePixelRatio );
        this.effect = AVR.stereoEffect(this.renderer);
        AVR.bindOrientationEvent(this, this._controlTarget);
    };
    VR.prototype.destroy = function () {
        var that = this;
        if (that.video) {
            that.video.pause();
            that.video = null;
        }
        if (that.audio) {
            that.audio.pause();
            that.audio = null;
        }
        if (that.hlsPlayer) {
            that.hlsPlayer.destroy();
        }
        if (that.flvPlayer) {
            that.flvPlayer.destroy();
        }
        for (var timer in that.timerList) {
            clearInterval(that.timerList[timer]);
        }
        that.destoryed = true;
    }
    VR.prototype.init = function (playUrlArray, extendsAnimationFrame, isLive) {
        var that = this;
        var startPos = new THREE.Vector2();
        var curPos = new THREE.Vector2();
        if (isLive) {
            that.isLive = true
        } else {
            that.isLive = false
        }
        that.playUrlArray = playUrlArray
        that.vrModel = false
        that.toolBar = AVR.toolBar(that.container, playUrlArray, that.isLive);
        var toolBar = that.toolBar;
        var spots = {},
            touches, timer, _s = 0;
        toolBar.defaultHeight = toolBar.toolbar.clientHeight;
        toolBar.defaultMaxHeight = toolBar.defaultHeight * 5;
        toolBar.isMouseDown = false;
        toolBar.toolbar.setAttribute("active", "true");
        that.toolBar.toolbar.addEventListener("click", function (event) {
            if (toolBar.pictureQualityBtn.getAttribute("active") == 'active') {
                toolBar.pictureQualityBox.style.display = 'none'
                btnInactive(toolBar.pictureQualityBtn);
                toolBar.pictureQualityBtn.removeAttribute("active");
            }
            event.stopPropagation()
        });
        that.container.addEventListener("click", function () {
            that.autoHideLeftTime = that.defaultAutoHideLeftTime;
            if (toolBar.pictureQualityBtn.getAttribute("active") == 'active') {
                toolBar.pictureQualityBox.style.display = 'none'
                btnInactive(toolBar.pictureQualityBtn);
                toolBar.pictureQualityBtn.removeAttribute("active");
            }
            if (!toolBar.toolbar.getAttribute("active")) {
                toolBar.toolbar.style.display = "block";
                toolBar.toolbar.setAttribute("active", "true");
            } else {
                toolBar.toolbar.style.display = "none";
                toolBar.toolbar.removeAttribute("active");
            }
        });
        toolBar.pictureQualityBtn.addEventListener("click", function (event) {
            event.stopPropagation()
            that.pictureQualityBtnClick();
        }, false);
        let pictureQualityItems = toolBar.pictureQualityBox.getElementsByTagName('div')
        for (let item of pictureQualityItems) {
            item.addEventListener("click", function () {
                that.pictureQualityBtnClick()

                toolBar.pictureQualityBtn.innerText = item.getAttribute('quality')
                that.quality = item.getAttribute('quality')
                that.play(item.getAttribute('url'), that.resType.sliceVideo, {
                    autoplay: true
                })
                that.beginBoxClick()
            })
        }

        toolBar.danmuBtn.addEventListener("click", function () {
            that.danmuBtnClick();
        }, false);
        if (AVR.isMobileDevice()) {
            toolBar.gyroBtn.addEventListener("click", function () {
                that.gyroBtnClick();
            }, false);
        }
        toolBar.f5Btn.addEventListener("click", function () {
            that.f5BtnClick();
        }, false);
        toolBar.beginBox.addEventListener("click", function () {
            that.beginBoxClick();
        }, false);
        toolBar.autoRotateBtn.addEventListener("click", function () {
            that.autoRotateBtnClick();
        }, false);
        toolBar.vrBtn.addEventListener("click", function () {
            that.vrBtnClick();
        }, false);
        toolBar.fullScreenBtn.addEventListener("click", function () {
            that.fullScreenBtnClick();
        }, false);

        that.container.addEventListener('touchstart', function (e) {
            that.touchStart(e);
        }, false);
        that.container.addEventListener('touchmove', function (e) {
            that.touchMove(e);
        }, false);
        that.container.addEventListener('touchend', function (e) {
            that.touchEnd(e);
        }, false);
        that.renderer.domElement.addEventListener('wheel', function (e) {
            var delta = e.deltaY > 0 ? 60 : -60;
            if (that.camera.fov + delta * 0.05 >= 10 && that.camera.fov + delta * 0.05 <= 120) {
                fovChange(delta);
            }
        }, false);
        that.f5BtnClick = function (e) {
            that.play(that.recUrl, that.resType.sliceVideo, {
                autoplay: true
            })
            that.beginBoxClick()
        }
        that.beginBoxClick = function (e) {
            that.toolBar.beginBox.remove()
            that._play();
            that.video.play();
            that.video.muted = false
            that.videoPlayHook();
            that.toolBar.toolbar.style.zIndex = '2'
        }
        that.autoRotateBtnClick = function (e) {
            var autoRotateBtn = that.toolBar.autoRotateBtn;
            if (autoRotateBtn.getAttribute("active") == 'active') {
                that.controls.autoRotate = false
                btnInactive(autoRotateBtn);
                autoRotateBtn.removeAttribute("active");
            } else {
                if (that.toolBar.gyroBtn) {
                    if (that.toolBar.gyroBtn.getAttribute("active") == 'active') {
                        AVR.msgBox('请先取消陀螺仪', 5, that.container);
                        return
                    }
                }
                btnActive(autoRotateBtn);
                that.controls.autoRotate = true
                autoRotateBtn.setAttribute("active", "active");
            }
        }
        that.danmuBtnClick = function (e) {
            var danmuBtn = that.toolBar.danmuBtn;
            if (danmuBtn.getAttribute("active") == 'active') {
                that.closeDanmu()
                danmuBtn.innerHTML = AVR.playerIcon.closeDanmuSvg
                danmuBtn.removeAttribute("active");
            } else {
                that.showDanmu()
                danmuBtn.innerHTML = AVR.playerIcon.danmuSvg
                danmuBtn.setAttribute("active", "active");
            }
        }
        that.gyroBtnClick = function (e) {
            var gyroBtn = that.toolBar.gyroBtn;
            if (gyroBtn.getAttribute("active") == 'active') {
                that.controls.gyroFreeze();
                btnInactive(gyroBtn);
                gyroBtn.removeAttribute("active");
            } else {
                that.controls.gyroUnfreeze();
                that.toolBar.autoRotateBtn.removeAttribute("active");
                btnInactive(that.toolBar.autoRotateBtn);
                gyroBtn.setAttribute("active", "active");
                btnActive(gyroBtn);
            }
        }
        if (AVR.isMobileDevice()) {
            that.gyroBtnClick();
        }
        that.fullScreenBtnClick = function (e) {
            var fullScreenBtn = that.toolBar.fullScreenBtn;
            if (!fullScreenBtn.getAttribute("fullscreen")) {
                btnActive(fullScreenBtn);
                fullScreenBtn.setAttribute("fullscreen", "true");
                AVR.fullscreen(that.container, true);
            } else {
                btnInactive(fullScreenBtn);
                fullScreenBtn.removeAttribute("fullscreen");
                AVR.fullscreen(that.container, false);
            }

        }
        that.vrBtnClick = function (e) {
            var vrBtn = that.toolBar.vrBtn;
            if (!vrBtn.getAttribute("vrmodel")) {
                btnActive(vrBtn);
                that.vrModel = true
                vrBtn.setAttribute("vrmodel", "true");
            } else {
                btnInactive(vrBtn);
                that.vrModel = false
                vrBtn.removeAttribute("vrmodel");
            }
        };
        that.pictureQualityBtnClick = function (e) {
            var pictureQualityBtn = that.toolBar.pictureQualityBtn;
            if (pictureQualityBtn.getAttribute("active") == 'active') {
                toolBar.pictureQualityBox.style.display = 'none'
                btnInactive(pictureQualityBtn);
                pictureQualityBtn.removeAttribute("active");
            } else {
                if (that.playUrlArray.length > 1) {
                    toolBar.pictureQualityBox.style.display = 'block'
                    pictureQualityBtn.setAttribute("active", "active");
                    btnActive(pictureQualityBtn);
                }
            }
        }

        that.touchStart = function (e) {
            if (e.targetTouches) {
                [].forEach.call(e.targetTouches, function (touch) {
                    if (spots[touch.identifier]) {
                        return;
                    }

                    spots[touch.identifier] = new THREE.Vector2(0, 0);

                })
                clearInterval(that.timerList.renderTouchersRimer);
                that.timerList.renderTouchersRimer = setInterval(function () {
                    renderTouches(touches);
                }, 1);
            }
        }

        function onmousedown(e) {
            toolBar.isMouseDown = true;
            var x = e.clientX || e.changedTouches[0].clientX;
            var y = e.clientY || e.changedTouches[0].clientY;
            startPos.set(x, y);
            curPos.set(x, y);
            that.autoHideLeftTime = that.defaultAutoHideLeftTime;
            toolBar.isActive = true;
        }

        that.touchEnd = function (e) {
            if (e.targetTouches) {
                [].forEach.call(e.changedTouches, function (touch) {
                    var spot = spots[touch.identifier];
                    if (spot) {
                        delete spots[touch.identifier];
                    }
                })
                if (e.targetTouches.length === 0) {
                    _s = 0;
                    that.controls.enable = true;
                    clearInterval(timer);
                }

            }
        }

        function onmouseup(e) {
            toolBar.isMouseDown = false;
        }
        that.touchMove = function (e) {
            touches = e.touches;
        }

        function onmousemove(e) {
            e.preventDefault();
            that.autoHideLeftTime = that.defaultAutoHideLeftTime;
            that.toolBar.isActive = true;
            if (toolBar.isMouseDown) {
                var x = e.clientX || e.changedTouches[0].clientX;
                var y = e.clientY || e.changedTouches[0].clientY;
                var offsetY = curPos.y - y;
                if (offsetY >= 5) {
                    slideBar(6);
                }
                if (offsetY <= -5) {
                    slideBar(-10);
                }
                curPos.set(x, y);
            }
        }

        function renderTouches(touches) {
            void 0 === that.controls.defaultDampingFactor && (that.controls.defaultDampingFactor = that.controls.dampingFactor);
            void 0 === that.controls.object.defaultFov && (that.controls.object.defaultFov = that.controls.object.fov);
            if (!touches) {
                return;
            };
            var num = 0,
                ids = [];
            [].forEach.call(touches, function (touch) {
                var spot = spots[touch.identifier];
                if (spot) {
                    spot.y = touch.pageY;
                    spot.x = touch.pageX;
                    ids.push(touch.identifier);
                }
                num++;
                if (num >= 2) {
                    var pos0 = spots[ids[0]];
                    var pos1 = spots[ids[1]];
                    var s = Math.sqrt(Math.pow(pos0.x - pos1.x, 2) + Math.pow(pos0.y - pos1.y, 2));
                    var s1 = (s - _s) / 4;
                    if (that.controls.object.fov - s1 < 140 && that.controls.object.fov - s1 > 10 && _s) {
                        that.controls.enable = false;
                        that.controls.object.fov -= s1;
                        that.controls.dampingFactor = that.controls.defaultDampingFactor * that.controls.object.defaultFov / that.controls.object.fov;
                    }
                    _s = s;
                    num = 0;
                    return;
                }
            })
        }

        function slideBar(h) {
            clearInterval(that.timerList.slideBarAniateTimer);
            that.timerList.slideBarAniateTimer = animateTimer = setInterval(function () {
                var step = (toolBar.toolbar.clientHeight + h);
                if (step >= toolBar.defaultHeight && step <= toolBar.defaultMaxHeight) {
                    toolBar.toolbar.style.height = step + "px";
                    toolBar.isActive = true;
                } else {
                    clearInterval(animateTimer);
                    if (h > 0) {
                        toolBar.isActive = true;

                        toolBar.toolbar.style.height = toolBar.defaultMaxHeight + "px";

                    } else {
                        toolBar.isActive = false;

                        toolBar.toolbar.style.height = toolBar.defaultHeight + "px";

                    }

                }
                that.autoHideLeftTime = that.defaultAutoHideLeftTime;
            }, 1);

        }

        function fovChange(delta) {
            that.camera.fov += delta * 0.05;
            that.camera.updateProjectionMatrix();
        }
        that.windowResize = function () {
            if (!AVR.isFullscreen()) {
                if (AVR.OS.isWeixin() && !AVR.OS.isiOS()) {
                    if (that.video.getAttribute('x5-video-orientation') == "landscape") {
                        btnActive(that.toolBar.vrBtn);
                    } else {
                        btnInactive(that.toolBar.vrBtn);
                    }
                    if (AVR.isCrossScreen()) {
                        btnActive(that.toolBar.vrBtn);
                    } else {
                        btnInactive(that.toolBar.vrBtn);
                    }
                } else {
                    if (AVR.isCrossScreen()) {
                        btnActive(that.toolBar.vrBtn);
                    } else {
                        btnInactive(that.toolBar.vrBtn);
                    }
                    btnInactive(that.toolBar.vrBtn);
                }
            } else {
                if (AVR.isMobileDevice()) {
                    if (AVR.isCrossScreen()) {
                        btnActive(that.toolBar.vrBtn);
                    } else {
                        btnInactive(that.toolBar.vrBtn);
                    }

                } else {
                    btnActive(that.toolBar.vrBtn);
                }
            }
        };
        window.addEventListener('resize', function () {
            bindVolumeEvent();
        }, false);

        function btnActive(obj) {
            obj.style.borderBottom = "1px solid #ccc";

            if (that.cameraEvt.controlGroup.length) {
                var pointObj = that.cameraEvt.controlGroup.getObjectByName("__focus");
                pointObj.visible = true;
            }
        }

        function btnInactive(obj) {
            obj.style.borderBottom = "none";
            if (that.cameraEvt.controlGroup.length) {
                var pointObj = that.cameraEvt.controlGroup.getObjectByName("__focus");
                pointObj.visible = false;
            }
        }

        that._play = function () {
            toolBar.btn.innerHTML = AVR.playerIcon.pauseSvg;
        }

        that._pause = function () {
            toolBar.btn.innerHTML = AVR.playerIcon.playSvg;
        }

        function bindVolumeEvent() {
            var Audio = that.video || that.audio;
            if (Audio) {
                var ract = AVR.getBoundingClientRect(that.container);
                toolBar.voice_bar.style.display = "block";
                var voice_bar = toolBar.voice_bar;
                var voice_slide_bar = voice_bar.firstChild;
                var voice_cur_slide_bar = voice_slide_bar.firstChild;
                var voice_btn = voice_cur_slide_bar.firstChild;
                var mouseDown = false,
                    touchStartY = 0,
                    touchCurrentY = 0,
                    tempY;
                Audio.volume = that.defaultVolume;
                var voice_bar_height = toolBar.voice_bar.clientHeight;
                var offset_h = (that.container.clientHeight - voice_bar_height) / 2;
                var h_top = voice_bar_height + offset_h;
                voice_cur_slide_bar.style.height = (Audio.volume * voice_bar_height) + "px";
                voice_bar.addEventListener("mousedown", function (e) {
                    voice_bar.style.opacity = 1;
                }, false);
                voice_slide_bar.addEventListener("click", function (e) {
                    var y = (e.clientY || e.changedTouches[0].clientY) - ract.top;
                    that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
                    var cur_h = h_top - y;
                    if (cur_h / voice_bar_height <= 1) {
                        voice_cur_slide_bar.style.height = cur_h + "px";
                        Audio.volume = cur_h / voice_bar_height;
                    }

                }, false);
                voice_bar.addEventListener("mouseout", function (e) {
                    mouseDown = false;
                }, false);
                voice_bar.addEventListener("mousedown", function (e) {
                    mouseDown = true;
                }, false);
                voice_bar.addEventListener("mouseup", function (e) {
                    mouseDown = false;
                }, false);
                voice_bar.addEventListener("mousemove", function (e) {
                    var y = (e.clientY || e.changedTouches[0].clientY) - ract.top;
                    that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
                    if (mouseDown) {
                        var cur_h = h_top - y;
                        voice_cur_slide_bar.style.height = cur_h + "px";
                        if (cur_h / voice_bar_height <= 1)
                            Audio.volume = cur_h / voice_bar_height;
                    }
                }, false);
                voice_bar.addEventListener("touchstart", function (e) {
                    e.preventDefault();
                    that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
                    tempY = voice_cur_slide_bar.clientHeight;
                    touchStartY = e.touches[0].pageY;
                    voice_bar.style.opacity = 1;
                }, false);
                voice_bar.addEventListener("touchmove", function (e) {
                    e.preventDefault();
                    that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;
                    touchCurrentY = e.touches[0].pageY;
                    var next_h = tempY + (touchStartY - touchCurrentY);
                    if (next_h / voice_bar_height <= 1) {
                        voice_cur_slide_bar.style.height = next_h + "px";
                        Audio.volume = next_h / voice_bar_height;
                    }
                }, false);
                voice_bar.addEventListener("touchend", function (e) {
                    tempY = 0;
                }, false);
                clearInterval(that.timerList.voiceBarActiveTimer);
                that.timerList.voiceBarActiveTimer = setInterval(function () {
                    if (that.voiceHideLeftTime <= 0) {
                        voice_bar.style.opacity = 0;
                    } else {
                        that.toolBar.isActive ? null : that.voiceHideLeftTime--;
                    }
                }, 1000);

            }
        }
        that.bindVolumeBar = bindVolumeEvent;

        function render() {
            if (that.destoryed) {
                return;
            }
            var width = that.container.offsetWidth;
            var height = that.container.offsetHeight;
            that.camera.aspect = width / height;
            if (that.vrModel) {
                that.cameraEvt.updatePosition();
                that.effect.setSize(width, height);
                that.effect.render(that.scene, that.camera);
            } else {
                that.renderer.setSize(width, height);
                that.renderer.setClearColor(new THREE.Color(0xffffff));
                that.renderer.render(that.scene, that.camera);
            }
            if (that._takeScreenShot) {
                that._takeScreenShot = false;
                var screenshot = that.renderer.domElement.toDataURL("image/jpeg");
                that._takeScreenShotCallback(screenshot);
            }
            that.camera.updateProjectionMatrix();
            if (that.controls) {
                that.controls.update();
            }
            extendsAnimationFrame();
        }

        function animate() {
            render();
            requestAnimationFrame(animate);
        }
        animate();
        //if you don't use an asteroid view,you need to initialize the controller after the asteroid view.
        // clearInterval(that.timerList.toolBarAutoHideTimer);
        // that.timerList.toolBarAutoHideTimer = setInterval(function () {
        //     if (!toolBar.isActive) {
        //         if (that.autoHideLeftTime < 0) {
        //             var pictureQualityBtn = that.toolBar.pictureQualityBtn;
        //             if (pictureQualityBtn.getAttribute("active") == 'active') {
        //                 toolBar.pictureQualityBox.style.display = 'none'
        //                 btnInactive(pictureQualityBtn);
        //                 pictureQualityBtn.removeAttribute("active");
        //             }
        //             that.autoHideLeftTime = that.defaultAutoHideLeftTime;
        //             toolBar.isActive = false;
        //         } else {
        //             that.autoHideLeftTime--;
        //         }
        //     }
        //     that.windowResize();
        // }, 1000);

    };
    VR.prototype.takeScreenShot = function (callback) {
        this._takeScreenShot = true;
        this._takeScreenShotCallback = callback;
    };
    Object.defineProperty(VR.prototype, 'playPanorama', {
        get: function () {
            console.warn('playPanorama() no longer supports. Use play() instead.');
            return VR.prototype.play;

        }
    });
    VR.prototype.play = function (recUrl, resType, options) {

        var playCfg = Object.assign(this.playCfg, options);
        var ids = ['__mxrealitySkybox', "__mxrealitySlice", "__mxrealityDefault"];
        for (var i in ids) {
            var obj = this.VRObject.getObjectByName(ids[i]);
            obj && (obj.visible = false);
            this.cubeCameraSphere && (this.cubeCameraSphere.visible = false);
        }
        var that = this;
        var toolBar = that.toolBar;
        that.recUrl = recUrl
        toolBar.loaddingIcon.style.display = 'flex'

        that._containerRadius = (that.resType.box == resType || that.resType.slice == resType) ? (that.vrbox.width / 2) : that.vrbox.radius;

        that.autoHideLeftTime = that.defaultAutoHideLeftTime;
        that.voiceHideLeftTime = that.defaultVoiceHideLeftTime;

        if (that.resType.box == resType) {
            var textures = [];
            var materials = [];

            var imageObj = new Image();
            imageObj.crossOrigin = "Anonymous";
            imageObj.src = recUrl;
            imageObj.onload = function () {
                var canvas, context;
                var tileWidth = imageObj.height;

                for (var i = 0; i < 6; i++) {
                    textures[i] = new THREE.Texture();
                    canvas = document.createElement('canvas');
                    context = canvas.getContext('2d');
                    canvas.height = tileWidth;
                    canvas.width = tileWidth;
                    context.drawImage(imageObj, tileWidth * i, 0, tileWidth, tileWidth, 0, 0, tileWidth, tileWidth);
                    textures[i].image = canvas;
                    textures[i].needsUpdate = true;
                    materials.push(new THREE.MeshBasicMaterial({
                        map: textures[i]
                    }));
                }
                var Box = that.VRObject.getObjectByName("__mxrealitySkybox");
                if (!Box) {
                    var Box = new THREE.Mesh(new THREE.CubeGeometry(that.vrbox.width, that.vrbox.height, that.vrbox.depth), new THREE.MultiMaterial(materials));
                    Box.applyMatrix(new THREE.Matrix4().makeScale(1, 1, -1));
                    Box.visible = true;
                    Box.name = "__mxrealitySkybox";
                    Box.matrixAutoUpdate = false;
                    Box.updateMatrix();
                    that.VRObject.add(Box);
                    toolBar.btn.addEventListener("click", function (e) {
                        that.controls.autoRotate ? that._pause() : that._play();
                        that.controls.autoRotate = !that.controls.autoRotate;
                    });
                } else {
                    Box.material = materials;
                }
                that.loadProgressManager.onLoad();
            }

        } else if (that.resType.slice == resType) {
            //cubeGeometry.scale(-1, 1, 1)
            var textureLoader = new THREE.TextureLoader(that.loadProgressManager);
            textureLoader.mapping = THREE.UVMapping;
            var materials = [];
            for (var i = 0; i < recUrl.length; i++) {
                var texture = textureLoader.load(recUrl[i]);
                materials.push(new THREE.MeshBasicMaterial({
                    map: texture
                }));
            }

            var cubeGeometry = new THREE.CubeGeometry(that.vrbox.width, that.vrbox.height, that.vrbox.depth, that.sliceSegment, that.sliceSegment, that.sliceSegment);
            var faceId = 0;
            var uv = [new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1)];

            for (var i = 0, l = cubeGeometry.faces.length; i < l; i += 2) {
                cubeGeometry.faces[i].materialIndex = faceId;
                cubeGeometry.faces[i + 1].materialIndex = faceId;
                cubeGeometry.faceVertexUvs[0][i] = [uv[3], uv[0], uv[2]];
                cubeGeometry.faceVertexUvs[0][i + 1] = [uv[0], uv[1], uv[2]];
                faceId++;
            }
            var obj = that.VRObject.getObjectByName("__mxrealitySlice");
            if (obj) {
                obj.material = materials;
                obj.geometry = cubeGeometry;
                obj.updateMatrix();
            } else {
                var cube = new THREE.Mesh(cubeGeometry, materials);
                cube.applyMatrix(new THREE.Matrix4().makeScale(1, 1, -1));
                cube.name = "__mxrealitySlice";
                cube.visible = true;
                cube.matrixAutoUpdate = false;
                cube.updateMatrix();
                that.VRObject.add(cube);
                that.cubeCamera = new THREE.CubeCamera(that._containerRadius, that.cameraPara.far, that.asteroidConfig.cubeResolution);
                var cubeCameraTexture = that.cubeCamera.renderTarget.texture;
                cubeCameraTexture.minFilter = THREE.LinearMipMapLinearFilter;

                that.VRObject.add(that.cubeCamera);
                material = new THREE.MeshBasicMaterial({
                    envMap: that.cubeCamera.renderTarget.texture,
                    side: THREE.BackSide
                });
                that.cubeCameraSphere = new THREE.Mesh(new THREE.SphereGeometry(that._containerRadius * that._cubeCameraTimes, 180, 180), material);
                that.cubeCameraSphere.position.set(0, 0, 0);
                that.cubeCameraSphere.name = "__mxrealitySlice";
                that.cubeCameraSphere.visible = true;
                that.cubeCameraSphere.matrixAutoUpdate = false;
                that.cubeCameraSphere.updateMatrix();
                that.VRObject.add(that.cubeCameraSphere);

                toolBar.btn.addEventListener("click", function (e) {
                    that.controls.autoRotate ? that._pause() : that._play();
                    that.controls.autoRotate = !that.controls.autoRotate;
                });
            }
            if (that.asteroidConfig.enable) {
                that.cubeCameraSphere.visible = true;
                that.asteroidForward = function (callback) {
                    that.cubeCamera.update(that.renderer, that.scene);
                    asteroidForward(callback);
                }
            } else {
                that.cubeCameraSphere.visible = false;
            }
        } else {
            var videoType = [that.resType.video, that.resType.sliceVideo, that.resType.flvVideo];
            if (videoType.indexOf(resType) >= 0) {
                if (!that.video) {
                    var video = that.video = AVR.createTag('video', {
                        'webkit-playsinline': true,
                        'playsinline': true,
                        'preload': 'auto',
                        'x-webkit-airplay': 'allow',
                        // 'x5-playsinline': true,
                        'x5-video-player-type': 'h5',
                        'x5-video-player-fullscreen': true,
                        'x5-video-orientation': 'portrait',
                        'style': 'object-fit: fill',
                        'loop': "loop"
                    }, {
                        'allowsInlineMediaPlayback': true,
                        'crossOrigin': "Anonymous"
                    });
                } else {
                    var video = that.video;
                    for (var node = 0; node < video.childNodes.length; node++) {
                        video.removeChild(video.childNodes[node]);
                    }
                }
                if (AVR.isMobileDevice()) {
                    video.muted = true;
                } else {
                    video.muted = false;
                }
                if (that.resType.sliceVideo == resType) {
                    function useHls() {
                        if (that.hlsPlayer) {
                            that.hlsPlayer.destroy()
                        }
                        that.hlsPlayer = new Hls(that.hlsConfig);
                        that.hlsPlayer.loadSource(recUrl);
                        that.hlsPlayer.attachMedia(video);
                    }

                    function useXMpegUrl() {
                        var source = AVR.createTag("source", {
                            src: recUrl,
                            type: 'application/x-mpegURL'
                        }, null);
                        video.appendChild(source);
                    }

                    function useVndAppleMpegUrl() {
                        video.src = recUrl;
                        video.addEventListener('loadedmetadata', function () {
                            video.play();
                        });
                    }
                    if (Hls.isSupported()) {
                        useHls();
                    } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
                        useVndAppleMpegUrl();
                    } else if (video.canPlayType('application/x-mpegURL')) {
                        useXMpegUrl();
                    } else {
                        console.error('The browser does not support the current live stream,' + recUrl)
                    }
                } else if (that.resType.flvVideo == resType) {
                    if (!flvjs.isSupported()) {
                        console.error('Your browser does not support flvjs')
                        return;
                    }
                    that.flvConfig.url = recUrl;
                    that.flvPlayer = flvjs.createPlayer(that.flvConfig);
                    that.flvPlayer.attachMediaElement(video);
                    that.flvPlayer.load();
                } else if (that.resType.video == resType) {
                    video.src = recUrl;
                }
                else if (video.canPlayType("application/vnd.apple.mpegurl")) {
                    video.src = recUrl;
                } else {
                    video.src = recUrl;
                }
                toolBar.loaddingIcon.style.display = 'none'
                toolBar.beginBox.style.display = 'flex'

                video.removeEventListener("canplaythrough", canplayThrough);
                toolBar.progressBar.removeEventListener("click", changeProgress);
                toolBar.btn.onclick = btnPlay
                video.addEventListener("canplaythrough", canplayThrough, false);
                toolBar.progressBar.addEventListener("click", changeProgress, false);
                video.load();
                that.onPlay()

                function btnPlay(e) {
                    if (video.paused) {
                        if (that.toolBar.autoRotateBtn.getAttribute("active") == 'active') {
                            that.controls.autoRotate = true
                        }
                        that.toolBar.beginBox.remove()
                        that._play();
                        video.play();
                        that.videoPlayHook();
                    } else {
                        that.controls.autoRotate = false
                        that._pause();
                        video.pause();
                        that.videoPauseHook();
                    }
                }

                function changeProgress(e) {
                    rect = AVR.getBoundingClientRect(that.container)
                    var x = (e.clientX || e.changedTouches[0].clientX) - rect.left;
                    video.currentTime = video.duration * (x / this.clientWidth);
                }
                that.video.buffTimer = null;

                function canplayThrough(e) {
                    toolBar.loaddingIcon.style.display = 'none'
                    toolBar.beginBox.style.display = 'flex'
                    if (!that.video.buffTimer) {
                        clearInterval(that.timerList.videoBuffTimer);
                        that.timerList.videoBuffTimer = that.video.buffTimer = setInterval(function (e) {
                            var allBuffered = 0;
                            if (video.buffered.length != 0) {
                                allBuffered += video.buffered.end(0);
                            }
                            if (allBuffered >= video.duration) {
                                clearInterval(that.video.buffTimer);
                            }
                            toolBar.loadedProgress.style.width = (allBuffered / video.duration) * 100 + "%";
                        }, 500);
                    }
                }
                var texture = new THREE.VideoTexture(video);
                texture.generateMipmaps = false;
                texture.minFilter = THREE.LinearFilter;
                texture.magFilter = THREE.LinearFilter;
                //texture.format = THREE.RGBFormat;
                texture.format = THREE.RGBAFormat;
                buildTexture(texture);

                clearInterval(that.timerList.videoProgressTimer);
                that.timerList.videoProgressTimer = that.video.progressTimer = setInterval(function (e) {
                    toolBar.playProgress.style.width = (video.currentTime / video.duration) * 100 + "%";
                    toolBar.curTime.innerText = AVR.formatSeconds(video.currentTime);
                    toolBar.totalTime.innerText = AVR.formatSeconds(video.duration);

                }, 1000);
                that.loadProgressManager.onLoad();
            } else {
                new THREE.TextureLoader(that.loadProgressManager).load(recUrl, function (texture) {
                    buildTexture(texture, true);
                });
            }

            function buildTexture(texture, isImg) {
                isImg = isImg || false;
                material = new THREE.MeshBasicMaterial({
                    overdraw: true,
                    map: texture
                });
                var obj = that.VRObject.getObjectByName("__mxrealityDefault");
                if (obj) {
                    obj.material = material;
                    obj.visible = true;
                } else {

                    var phiStart = -Math.PI / 2;
                    var geometry = new THREE.SphereBufferGeometry(that.vrbox.radius, that.vrbox.widthSegments, that.vrbox.heightSegments, phiStart);
                    geometry.scale(-1, 1, 1); //x取反（面朝里）
                    mesh = new THREE.Mesh(geometry, material);
                    mesh.visible = true;
                    mesh.name = "__mxrealityDefault";
                    if (isImg) {
                        mesh.matrixAutoUpdate = false;
                        mesh.updateMatrix();
                    }
                    that.VRObject.add(mesh);
                }
                if (that.asteroidConfig.enable) {
                    that.asteroidForward = function (callback) {
                        asteroidForward(callback);
                    }
                }

            }
        }

        function asteroidForward(callback) {
            that.controls && (that.controls.reset(), that.controls.enable = false);
            var config = that.asteroidConfig;
            var defaultFov = that.camera.fov;
            var s = that._containerRadius * (that._cubeCameraTimes * 0.9);
            that.camera.position.y = s * config.asteroidTop;
            that.camera.rotation.x = THREE.Math.degToRad(-90);

            that.camera.fov = config.asteroidFov;

            var t = config.asteroidForwardTime * config.asteroidFPS / 300;
            var v = s / t;
            var sFov = that.camera.fov - defaultFov;
            var vFov = sFov / t;
            var vRo = Math.PI / 2 / t;
            var yDown = false,
                fovDone = false;
            var tmpTarget = new THREE.Vector3(that._controlTarget.x, that._controlTarget.y, that._controlTarget.z);

            setTimeout(function () {
                that.timerList.asteroidForwardTimer = asteroidForwardTimer = setInterval(function () {
                    if (config.asteroidTop * that.camera.position.y - v >= 0) {
                        that.camera.position.y -= (v * config.asteroidTop);
                        that.camera.lookAt(tmpTarget);
                        tmpTarget.z *= 1.25;
                    } else {
                        yDown = true;
                    }
                    if (that.camera.fov - vFov >= defaultFov) {
                        that.camera.fov -= vFov;
                    } else {
                        fovDone = true;
                    }
                    if (yDown && fovDone) {
                        clearInterval(asteroidForwardTimer);
                        that.controls.enable = true;
                        that.camera.position.y = 0;
                        that.camera.fov = defaultFov;

                        if (void 0 !== callback) {
                            callback();
                        }
                    }
                }, config.asteroidFPS);
            }, config.asteroidWaitTime);
        }

    };
    VR.prototype.sphere2BoxPano = function (img, w, h, callback) {
        var that = this;
        var fases = {
            'x': 'x',
            'nx': 'nx',
            'ny': 'ny',
            'y': 'y',
            'z': 'z',
            'nz': 'nz'
        };
        var canvasArr = [],
            finishNum = 0;
        var i = 0;
        var image = new Image();
        image.crossOrigin = "Anonymous";
        image.src = img;
        image.onload = function () {
            for (var id in fases) {
                var canvas = document.createElement('canvas');
                canvas.width = w;
                canvas.height = h;
                canvas.id = "face_" + id;
                canvasArr[i] = canvas;
                var gl = canvas.getContext('webgl', {
                    preserveDrawingBuffer: true
                }); //获取canvas上下文
                var shaderPorgram = initShaders(gl, id); //初始化着色器程序

                var num = initVertexBuffers(gl, shaderPorgram);
                var PI = gl.getUniformLocation(shaderPorgram, 'PI');
                gl.uniform1f(PI, Math.PI);

                gl.clearColor(0.0, 0.0, 0.0, 1.0);

                // Set texture
                if (!initTextures(gl, shaderPorgram, num, image)) {
                    console.log('Failed to intialize the texture.');
                    //return;
                }
                i++;
            }
        }

        //初始化纹理
        function initTextures(gl, shaderPorgram, n, image) {
            var texture = gl.createTexture(); //创建纹理对象

            if (!texture) {
                console.log('Failed to create the texture object!');
                return false;
            }

            var u_Sampler = gl.getUniformLocation(shaderPorgram, 'u_Sampler');

            loadTextures(gl, n, texture, u_Sampler, image);
            return true;
        }

        //加载纹理图片
        function loadTextures(gl, n, texture, u_Sampler, image) {
            if (that.asteroidConfig.enable) {
                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, -1); //对纹理图像进行y轴反转
            }
            gl.activeTexture(gl.TEXTURE0); //激活纹理单元
            gl.bindTexture(gl.TEXTURE_2D, texture); //绑定纹理对象

            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); //配置纹理对象的参数

            /**
             * RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.
             * 大致意思是纹理没有渲染成功，因为所使用的图片的分辨率不是2的幂数，2的幂数是指2*2、4*4、8*8、16*16...256*256...；
             * 需要设置图形纹理参数时设置水平垂直拉伸。
             */
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image); //将纹理图像分配给纹理对象

            gl.uniform1i(u_Sampler, 0); //将0号纹理传给着色器中的取样器变量

            gl.clear(gl.COLOR_BUFFER_BIT); // Clear <canvas>
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle
            if (finishNum < 5) {
                finishNum++;
            } else {
                callback(getNewPano());
            }
            //gl.drawArrays(gl.TRIANGLE_STRIP, 1, n); // Draw the rectangle
        }

        //初始化顶点位置
        function initVertexBuffers(gl, shaderPorgram) {
            //顶点坐标和纹理坐标映射关系
            var datas = new Float32Array([
                //顶点坐标、纹理坐标
                -1.0, 1.0, 0.0, 1.0,
                -1.0, -1.0, 0.0, 0.0,
                1.0, 1.0, 1.0, 1.0,
                1.0, -1.0, 1.0, 0.0,
            ]);

            var num = 4; //顶点数目
            var vertexBuffer = gl.createBuffer(); //创建缓冲区对象

            if (!vertexBuffer) {
                console.log('Failed to create the buffer object!');
                return -1;
            }

            //将缓冲区对象绑定到目标并写入数据
            gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, datas, gl.STATIC_DRAW);

            var size = datas.BYTES_PER_ELEMENT; //数组中的每个元素的大小（以字节为单位）

            //顶点着色器接受顶点坐标和纹理坐标映射关系
            var a_Position = gl.getAttribLocation(shaderPorgram, 'a_Position');
            gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, size * 4, 0);
            gl.enableVertexAttribArray(a_Position);

            var a_TexCoord = gl.getAttribLocation(shaderPorgram, 'a_TexCoord');
            gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, size * 4, size * 2);
            gl.enableVertexAttribArray(a_TexCoord);

            return num;
        }
        //初始化着色器
        function initShaders(gl, type) {
            var shaderProgram;
            var fragmentShader = getShader(gl, type);
            var vertexShader = getShader(gl);
            //创建着色器
            shaderProgram = gl.createProgram();
            gl.attachShader(shaderProgram, vertexShader);
            gl.attachShader(shaderProgram, fragmentShader);
            //链接着色器程序
            gl.linkProgram(shaderProgram);
            //检查着色器是否成功链接
            if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
                return null;
            }
            //链接成功后激活渲染器程序
            gl.useProgram(shaderProgram);

            //启用顶点缓冲区数组
            gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
            shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
            //gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
            shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
            shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
            return shaderProgram;
        }

        //根据id获得编译好的着色器
        function getShader(gl, id) {
            var shaderScript;
            var shader;

            //创建顶点着色器或片段着色器
            if (id) {
                shaderScript = getShaderFragment(id);
                if (!shaderScript) {
                    return null;
                }
                shader = gl.createShader(gl.FRAGMENT_SHADER);
            } else {
                shaderScript = getShaderVertex()
                shader = gl.createShader(gl.VERTEX_SHADER);
            }
            gl.shaderSource(shader, shaderScript);
            //编译着色器代码
            gl.compileShader(shader);
            //检查是否编译成功
            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                console.log(gl.getShaderInfoLog(shader)); //打印编译失败信息
                return null;
            }
            //成功编译返回编译好的着色器
            return shader;
        }

        //<!-- 片段着色器程序 -->
        function getShaderFragment(type) {
            var code = "";
            var variable = "\n\
        precision mediump float;\n\
        varying vec2 v_TexCoord;\n\
        uniform sampler2D u_Sampler;\n\
        uniform float PI;\n";

            //超出范围处理\
            var checkRange = "\n\
        if(abs(theta)>PI){\n\
            if(theta>PI){\n\
                theta -= 2.0*PI;\n\
            }else{\n\
                theta += 2.0*PI;\n\
            }\n\
        }\n\
        if(abs(phi)>PI/2.0){\n\
            if(phi>PI/2.0){\n\
                phi -= PI;\n\
            }else{\
                phi += PI;\n\
            }\n\
        }\n\
        float x = theta/PI*0.5 + 0.5;\n\
        float y = phi/PI*2.0*0.5 + 0.5;\n\
        gl_FragColor = texture2D(u_Sampler, vec2(x,y));\n";
            if (type == 'z') {
                //z轴正平面-z\
                code = variable + "\n\
			void main() {\n\
				float r = 0.5;\n\
				vec2 orig = vec2(0.5-v_TexCoord.x,v_TexCoord.y-0.5);\n\
				float theta = atan(orig.x,r);\n\
				float phi = atan(orig.y*cos(theta),r);" + checkRange + "\n\
			}\n";
            } else if (type == "nz") {
                //z轴负平面-nz\
                code = variable + "\n\
			void main() {\n\
				float r = 0.5;\n\
				vec2 orig = vec2(0.5-v_TexCoord.x,v_TexCoord.y-0.5);\n\
				float theta = atan(orig.x,r);\n\
				float phi = atan(orig.y*cos(theta),r);\n\
        		theta = theta+PI;\n" + checkRange + "\n\
			}\n";
            } else if (type == "x") {
                //x轴正平面-x\
                code = variable + "\n\
			void main() {\n\
				float r = 0.5;\n\
				vec2 orig = vec2(v_TexCoord.x-0.5,v_TexCoord.y-0.5);\n\
				float theta = atan(r,orig.x);\n\
				float phi = atan(orig.y*sin(theta),r);" + checkRange + "\n\
			}\n";
            } else if (type == "nx") {
                //x轴负平面-nx\
                code = variable + "\n\
			void main() {\n\
				float r = 0.5;\n\
				vec2 orig = vec2(v_TexCoord.x-0.5,v_TexCoord.y-0.5);\n\
				float theta = atan(r,orig.x);\n\
				float phi = atan(orig.y*sin(theta),r);\n\
        		theta = theta+PI;" + checkRange + "\n\
			}\n";
            } else if (type == "y") {
                //y轴正平面-y\
                code = variable + "\n\
			void main() {\n\
				float r = 0.5;\n\
				vec2 orig = vec2(0.5-v_TexCoord.x,0.5-v_TexCoord.y);\n\
        		float theta = atan(orig.x,orig.y);\n\
        		float phi = atan(r*sin(theta),orig.x);" + checkRange + "\n\
			}\n";
            } else if (type == "ny") {
                //y轴负平面-ny
                code = variable + "\n\
			void main() {\n\
				float r = 0.5;\n\
				vec2 orig = vec2(0.5-v_TexCoord.x,v_TexCoord.y-0.5);\n\
				float theta = atan(orig.x,orig.y);\n\
				float phi = atan(r*sin(theta),orig.x);\n\
				phi = -phi;" + checkRange + "\n\
			}\n";
            } else {
                console.error("shader fragment type error!");
            }
            return code;
        }

        function getShaderVertex() {
            var code = "\n\
        attribute vec4 a_Position;\n\
        attribute vec2 a_TexCoord;\n\
        varying vec2 v_TexCoord;\n\
        void main() {\n\
            gl_Position= a_Position;\n\
            v_TexCoord = a_TexCoord;\n\
        }\n";
            return code;
        }

        function getNewPano() {
            var c = document.createElement('canvas'),
                ctx = c.getContext('2d');
            c.width = w * 6;
            c.height = h;

            var tmp = document.createElement('canvas'),
                tmpctx = tmp.getContext('2d');
            tmp.width = w;
            tmp.height = h;
            var degree = 180 * Math.PI / 180;
            tmpctx.rotate(degree);
            if (that.sliceSegment) {
                var sliceArray = [];
                var canvasCell = document.createElement("canvas");
                canvasCell.width = h / that.sliceSegment;
                canvasCell.height = h / that.sliceSegment;
                var canvasCtx = canvasCell.getContext("2d");
                for (var idx in canvasArr) {
                    tmpctx.drawImage(canvasArr[idx], 0, 0, -w, -h);
                    for (var row = 0; row < that.sliceSegment; row++) {
                        for (var col = 0; col < that.sliceSegment; col++) {
                            canvasCtx.putImageData(tmpctx.getImageData(col * (h / that.sliceSegment), row * (h / that.sliceSegment), h * (col + 1) / that.sliceSegment, h * (row + 1) / that.sliceSegment), 0, 0);
                            sliceArray.push(canvasCell.toDataURL("image/jpeg"));
                        }
                    }
                }
                return sliceArray;
            } else {
                for (var idx in canvasArr) {
                    tmpctx.drawImage(canvasArr[idx], 0, 0, -w, -h);
                    ctx.drawImage(tmp, w * idx, 0, w, h);
                }
                return c.toDataURL("image/jpeg");
            }
        };

    }

    var AR = function (scene, renderer, container, cameraPara, cameraPosition) {
        var that = this;
        this.scene = scene;
        this.renderer = renderer;
        this.container = container;
        AVR.setCameraPara(that, cameraPara, cameraPosition);
        this.constraints = {};
        this.video = null;
        this.openAudio = false;

        this.cameraIndex = 1; //0为前置摄像头，否则为后置

        this._controlTarget = new THREE.Vector3(0.0001, 0, 0);
        this.camera = new THREE.PerspectiveCamera(this.cameraPara.fov, this.cameraPara.aspect, this.cameraPara.near, this.cameraPara.far);
        this.camera.position.set(this.cameraPosition.x, this.cameraPosition.y, this.cameraPosition.z);

        this.cameraReady = false;
        this.scene.add(this.camera);
        this.clock = new THREE.Clock();
        this.tempCanvas = document.createElement('canvas');
        this.effect = AVR.stereoEffect(this.renderer);
        this._takeScreenShot = false;
    }
    AR.prototype.init = function () {
        var self = this;
        AVR.bindOrientationEvent(self, self._controlTarget);
        this.video = AVR.createTag('video', {
            'webkit-playsinline': true,
            'playsinline': true,
            'preload': 'auto',
            'x-webkit-airplay': 'allow',
            'x5-playsinline': true,
            'x5-video-player-type': 'h5',
            'x5-video-player-fullscreen': true,
            'x5-video-orientation': 'portrait',
            'style': 'object-fit: fill'
        }, {
            'allowsInlineMediaPlayback': true
        });

        //this.video.style.display = "none";
        this.video.style.zIndex = "-99999";
        this.video.style.position = "absolute";
        this.video.style.left = "0px";
        this.video.style.top = "0px";
        this.video.style.width = "2px";
        this.video.style.height = "2px";
        document.body.appendChild(this.video);
        this.video.oncanplaythrough = function () {
            self.cameraReady = true;
            if (self.video.readyState === self.video.HAVE_ENOUGH_DATA) {
                self.cameraTexture = new THREE.VideoTexture(self.video);
                self.cameraTexture.generateMipmaps = false;
                self.cameraTexture.format = THREE.RGBAFormat;
                self.cameraTexture.maxFilter = THREE.NearestFilter;
                self.cameraTexture.minFilter = THREE.NearestFilter;
                self.scene.background = self.cameraTexture; // 背景视频纹理
                self.cameraTexture.needsUpdate = true;
            }
        }

        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
        window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

        if (navigator.getUserMedia) {
            var medias = {
                audio: self.openAudio,
                video: {
                    facingMode: {
                        exact: self.cameraIndex ? "environment" : "user"
                    }
                }
            }
            navigator.getUserMedia(medias, successCallback, errorCallback);
        } else {
            alert('Native device meadia streaming(getUserMdeia) not supported in this browser.')
        }

        function successCallback(stream) {
            self.video.srcObject = stream;
        };

        function errorCallback(err) {
            alert(err);
        };
    }
    AR.prototype.takeCameraPhoto = function () {
        var ctx = this.tempCanvas.getContext('2d');
        ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
        ctx.drawImage(this.video, 0, 0, window.innerWidth, window.innerHeight); //将video对象内指定的区域捕捉绘制到画布上指定的区域，实现拍照。
        return ctx.toDataURL("image/jpeg");
    }
    AR.prototype.takeScreenShot = function (callback) {
        this._takeScreenShot = true;
        this._takeScreenShotCallback = callback;
    }
    AR.prototype.play = function () {
        var that = this;

        function render() {

            if (that._takeScreenShot) {
                that._takeScreenShot = false;
                var screenshot = that.renderer.domElement.toDataURL("image/jpeg");
                that._takeScreenShotCallback(screenshot);
            }
            if (that.cameraReady) {
                var width = window.innerWidth;
                var height = window.innerHeight;
                that.camera.aspect = width / height;
                that.cameraTexture.repeat.y = height / that.video.videoHeight;
                that.cameraTexture.offset.x = 0;
                that.cameraTexture.offset.y = 0;
                if ((AVR.isMobileDevice() && AVR.isCrossScreen())) {
                    that.cameraTexture.repeat.x = width / (2 * that.video.videoWidth);
                    that.effect.setSize(width, height);
                    that.effect.render(that.scene, that.camera);
                } else {
                    that.cameraTexture.repeat.x = width / that.video.videoWidth;
                    that.renderer.setSize(width, height);
                    that.renderer.setClearColor(new THREE.Color(0xffffff));
                    that.renderer.render(that.scene, that.camera);
                }
                that.camera.updateProjectionMatrix();
            }
            if (that.controls) {
                that.controls.update(that.clock.getDelta());
            }

        }

        function animate() {
            requestAnimationFrame(animate);
            render();
        }
        animate();

    }

    var AVR = {
        debug: false,
        playerIcon: {
            loaddingSvg: '<svg t="1607057815176" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4004" width="48" height="48"><path d="M888.23 392.083H718.385c-21.668 0-39.194-17.556-39.194-39.196 0-21.638 17.527-39.194 39.194-39.194h68.182c-61.504-86.907-162.641-143.715-277.223-143.715-187.607 0-339.692 152.086-339.692 339.69 0 187.606 152.086 339.69 339.692 339.69s339.69-152.085 339.69-339.69c0-21.638 17.527-39.194 39.194-39.194 21.64 0 39.197 17.556 39.197 39.194 0 230.899-187.2 418.082-418.082 418.082-230.885 0-418.083-187.182-418.083-418.082 0-230.898 187.198-418.081 418.083-418.081 140.127 0 263.895 69.086 339.691 174.935v-70.415c0-21.64 17.527-39.195 39.194-39.195 21.64 0 39.197 17.555 39.197 39.195v156.78c0.002 21.64-17.557 39.196-39.195 39.196z" fill="#ffffff" p-id="4005"></path></svg>',
            pictureQualitySvg: '<svg t="1606979917924" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2927" width="22" height="22"><path d="M256 112a16 16 0 0 1 16 16v128a16 16 0 0 0 16 16h128a16 16 0 0 1 16 16v128a16 16 0 0 0 16 16h144v144a16 16 0 0 0 16 16h144v144a16 16 0 0 0 16 16h128a16 16 0 0 1 16 16v128a16 16 0 0 1-16 16H128a16 16 0 0 1-16-16V128a16 16 0 0 1 16-16h128z m640 320a16 16 0 0 1 16 16v128a16 16 0 0 1-16 16h-128a16 16 0 0 1-16-16v-128a16 16 0 0 1 16-16h128zM736 272a16 16 0 0 1 16 16v128a16 16 0 0 1-16 16h-128a16 16 0 0 1-16-16v-128a16 16 0 0 1 16-16h128zM896 112a16 16 0 0 1 16 16v128a16 16 0 0 1-16 16h-128a16 16 0 0 1-16-16V128a16 16 0 0 1 16-16h128zM576 112a16 16 0 0 1 16 16v128a16 16 0 0 1-16 16h-128a16 16 0 0 1-16-16V128a16 16 0 0 1 16-16h128z" p-id="2928" fill="#ffffff"></path></svg>',
            playSvg: '<svg t="1596623860726" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32635" width="32" height="32"><path fill="#ffffff" d="M744.727273 551.563636L325.818182 795.927273c-30.254545 18.618182-69.818182-4.654545-69.818182-39.563637v-488.727272c0-34.909091 39.563636-58.181818 69.818182-39.563637l418.909091 244.363637c30.254545 16.290909 30.254545 62.836364 0 79.127272z" p-id="32636"></path></svg>',
            pauseSvg: '<svg t="1596624663266" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32779" width="32" height="32"><path fill="#ffffff" d="M442.181818 709.818182c0 37.236364-30.254545 69.818182-69.818182 69.818182s-69.818182-30.254545-69.818181-69.818182v-395.636364c0-37.236364 30.254545-69.818182 69.818181-69.818182s69.818182 30.254545 69.818182 69.818182v395.636364z m279.272727 0c0 37.236364-30.254545 69.818182-69.818181 69.818182s-69.818182-30.254545-69.818182-69.818182v-395.636364c0-37.236364 30.254545-69.818182 69.818182-69.818182s69.818182 30.254545 69.818181 69.818182v395.636364z" p-id="32780"></path></svg>',
            resetLookAtSvg: '<svg t="1596624710564" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32923" width="22" height="22"><path fill="#ffffff" d="M512 512m-163.2 0a163.2 163.2 0 1 0 326.4 0 163.2 163.2 0 1 0-326.4 0Z" fill="#333333" p-id="32924"></path><path fill="#ffffff" d="M512 153.6A358.4 358.4 0 1 1 153.6 512 358.4 358.4 0 0 1 512 153.6M512 64a448 448 0 1 0 448 448A448 448 0 0 0 512 64z" fill="#333333" p-id="32925"></path></svg>',
            gyroSvg: '<svg t="1608877163460" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4546" width="24" height="24"><path d="M889.9 503.2c-3.7-157.7-106.6-301-262.9-350.8l4.9-18.2c2.6-9.6-3.1-19.5-12.7-22-9.6-2.6-19.5 3.1-22 12.7l-4.9 18.2c-160.3-35-321.1 37.7-403.1 172.3-60.5 14.6-101.5 41.7-111.8 80.1C67 434 88.9 478 134.1 521c3.8 157.6 106.7 300.7 262.9 350.6l-4.9 18.2c-2.6 9.6 3.1 19.5 12.7 22 9.6 2.6 19.5-3.1 22-12.7l4.9-18.2c160.2 34.9 320.9-37.6 403-172.2 60.7-14.6 101.6-41.8 111.9-80.3C957 590 935 546.1 889.9 503.2zM617.7 187.1c129.2 42 218 155.2 233.8 283.8-52.7-39.3-123.9-76.4-206.9-106L611 490.2c49.5 22.9 80 49.1 74.8 68.4-7.2 27-81.8 30.9-170.4 10l102.3-381.5z m-34.8-9.3L480.7 559.2c-87.2-26.2-149.8-66.8-142.6-93.8 5.2-19.3 44.7-26.7 99-21.8l33.6-125.3c-86.6-15.8-166.8-19.3-232.2-11.6C316.6 203.2 450 149.6 582.9 177.8zM406.3 836.9c-129.2-42-217.9-155.1-233.8-283.7C239.3 603 335.9 649.1 448 681l-41.7 155.9z m34.8 9.3l41.8-155.8c113.1 28.4 219.8 36.8 302.5 27.1-78 103.3-211.4 156.9-344.3 128.7z" fill="#ffffff" p-id="4547"></path></svg>',
            vrSvg: '<svg t="1608876953264" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3475" width="24" height="24" data-spm-anchor-id="a313x.7781069.0.i9"><path d="M957.44 377.856c-1.024-4.096-2.048-9.216-3.072-13.312 0-2.048-1.024-3.072-1.024-4.096-2.048-7.168-5.12-14.336-9.216-20.48l-41.984-97.28c-17.408-40.96-55.296-68.608-99.328-73.728-6.144-1.024-10.24-1.024-15.36-2.048-92.16-8.192-184.32-13.312-275.456-13.312s-183.296 5.12-274.432 13.312c-4.096 0-9.216 1.024-15.36 2.048-44.032 5.12-81.92 32.768-99.328 73.728l-41.984 97.28c-3.072 6.144-6.144 13.312-9.216 20.48-1.024 1.024-1.024 3.072-1.024 4.096-1.024 4.096-2.048 8.192-3.072 13.312C56.32 439.296 51.2 501.76 51.2 563.2c0 61.44 5.12 122.88 15.36 183.296 9.216 53.248 53.248 95.232 106.496 101.376 65.536 8.192 109.568 12.288 131.072 14.336h5.12c43.008 0 79.872-39.936 115.712-79.872 28.672-30.72 61.44-66.56 86.016-66.56s57.344 34.816 86.016 66.56c37.888 40.96 76.8 82.944 120.832 79.872 22.528-2.048 66.56-6.144 131.072-14.336 54.272-6.144 97.28-48.128 106.496-101.376 10.24-61.44 15.36-122.88 15.36-183.296 2.048-61.44-3.072-123.904-13.312-185.344zM159.744 259.072c11.264-26.624 36.864-46.08 66.56-49.152 5.12-1.024 10.24-1.024 15.36-2.048C330.752 198.656 421.888 194.56 512 194.56c90.112 0 181.248 4.096 271.36 13.312 4.096 0 9.216 1.024 15.36 2.048 29.696 3.072 54.272 21.504 66.56 49.152l10.24 23.552c-7.168-2.048-15.36-4.096-23.552-5.12-112.64-14.336-226.304-20.48-338.944-20.48s-226.304 7.168-338.944 20.48c-8.192 1.024-15.36 3.072-23.552 5.12l9.216-23.552z m756.736 481.28c-6.144 35.84-34.816 63.488-70.656 67.584-64.512 7.168-108.544 12.288-130.048 14.336-25.6 2.048-58.368-34.816-88.064-66.56C591.872 716.8 555.008 675.84 512 675.84c-43.008 0-79.872 40.96-115.712 79.872-29.696 31.744-63.488 68.608-88.064 66.56-21.504-2.048-65.536-6.144-130.048-14.336-35.84-4.096-65.536-31.744-70.656-67.584C97.28 680.96 92.16 621.568 92.16 563.2c0-59.392 5.12-118.784 15.36-178.176 1.024-4.096 2.048-7.168 3.072-11.264l6.144-15.36c12.288-22.528 34.816-37.888 61.44-40.96 110.592-13.312 223.232-20.48 333.824-20.48s223.232 7.168 333.824 20.48c26.624 3.072 49.152 18.432 61.44 40.96l6.144 15.36c1.024 4.096 2.048 7.168 3.072 11.264 10.24 59.392 15.36 118.784 15.36 178.176 0 58.368-5.12 117.76-15.36 177.152zM440.32 537.6C440.32 608.256 382.976 665.6 312.32 665.6S184.32 608.256 184.32 537.6 241.664 409.6 312.32 409.6 440.32 466.944 440.32 537.6z m399.36 0C839.68 608.256 782.336 665.6 711.68 665.6S583.68 608.256 583.68 537.6 641.024 409.6 711.68 409.6 839.68 466.944 839.68 537.6z" p-id="3476" fill="#ffffff"></path></svg>',
            fullScreenSvg: '<svg t="1607059281037" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3162" width="18" height="18"><path d="M628.053333 628.053333a32 32 0 0 1 45.226667 0l158.72 158.634667V693.333333l0.298667-4.352A32 32 0 0 1 896 693.333333v181.333334l-0.341333 3.84a21.333333 21.333333 0 0 1-20.992 17.493333h-181.333334l-4.352-0.298667a32 32 0 0 1-27.648-31.701333l0.298667-4.352a32 32 0 0 1 31.701333-27.648h93.44l-158.72-158.72-3.114666-3.584a32 32 0 0 1 3.114666-41.642667z m-232.106666 0a32 32 0 0 1 3.114666 41.642667l-3.114666 3.584-158.72 158.72h93.44a32 32 0 0 1 31.701333 27.648l0.298667 4.352a32 32 0 0 1-27.648 31.701333L330.666667 896H149.333333a21.333333 21.333333 0 0 1-20.992-17.493333L128 874.666667v-181.333334a32 32 0 0 1 63.701333-4.352l0.298667 4.352v93.354667l158.72-158.634667a32 32 0 0 1 45.226667 0zM874.666667 128a21.333333 21.333333 0 0 1 20.992 17.493333L896 149.333333v181.333334a32 32 0 0 1-63.701333 4.352L832 330.666667V237.312L673.28 395.946667a32 32 0 0 1-48.341333-41.642667l3.114666-3.584 158.72-158.72h-93.44a32 32 0 0 1-31.701333-27.648L661.333333 160a32 32 0 0 1 27.648-31.701333L693.333333 128h181.333334zM330.666667 128l4.352 0.298667a32 32 0 0 1 27.648 31.701333l-0.298667 4.352a32 32 0 0 1-31.701333 27.648H237.226667l158.72 158.72 3.114666 3.584a32 32 0 0 1-48.341333 41.642667L192 237.312V330.666667l-0.298667 4.352A32 32 0 0 1 128 330.666667V149.333333l0.341333-3.84A21.333333 21.333333 0 0 1 149.333333 128h181.333334z" p-id="3163" fill="#ffffff"></path></svg>',
            audioPlaySvg: '<svg t="1596624803551" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="33362" width="24" height="24"><path d="M491.857752 129.427768L245.206166 319.922357v4.37361h-90.428545c-49.776683 0-90.49199 38.923498-90.491991 86.594217v216.422098c0 47.733141 40.715307 86.594217 90.491991 86.594217h90.428545v4.373611l246.651586 192.617949c6.980995 6.404873 15.566534 10.887978 24.888854 12.994966 24.824385 6.560416 45.182039-6.497994 45.182038-30.302144V146.734946c0-8.622378-2.233877-17.243733-6.764054-21.617344-13.529131-17.306154-42.949184-15.182794-63.306838 4.310166zM767.738034 200.902636c-16.20303-8.231475-36.153408-2.50096-45.246507 12.994965-9.0624 15.181771-2.297322 34.549887 13.592576 43.297109 92.725868 49.731658 153.798828 151.507646 153.798828 261.906012S828.809971 731.274052 736.084103 781.069155c-15.889899 8.622378-22.654976 28.115338-13.592576 43.234687 6.106068 10.345626 17.222243 16.885576 29.420053 17.306154v0.062422a43.382043 43.382043 0 0 0 15.826454-4.373611c117.614721-62.727647 189.982936-183.996594 189.982935-318.198085s-72.368214-255.470439-189.982935-318.198086z" p-id="33363"></path><path d="M822.351885 517.591345c0-101.966323-60.489676-189.33109-146.55075-213.646891-18.563798-4.825912-37.190017 7.30129-41.862433 26.728758-4.799306 18.922978 6.479575 38.189787 25.572421 43.681871 55.879682 16.953114 95.343485 75.237565 95.343486 145.649218 0 70.349231-39.46278 131.046638-95.343486 145.586796-19.092847 5.493108-30.371728 24.758893-25.572421 43.681872 2.336208 17.015535 16.290011 26.728758 32.581046 26.728758v0.061398c2.336208 0 6.945179 0 9.344832-4.825912 85.998653-21.839401 146.487306-111.678522 146.487305-213.645868z" p-id="33364"></path></svg>',
            audioPauseSvg: '<svg t="1596624838920" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="33507" width="24" height="24"><path d="M225.680461 326.598406c-0.419556-0.019443-0.818645-0.019443-1.237177-0.019443L101.812315 326.578963c-22.753213 0-40.876989 18.24248-40.876989 40.777729l0 286.336424c0 22.534226 18.302855 40.777729 40.876989 40.777729l122.629945 0c0.079818 0 0.119727 0 0.198521 0l0 0.157589 300.289204 194.444551c7.125281 6.108115 16.405645 9.781784 26.526143 9.781784 22.573111 0 40.874943-18.301831 40.874943-40.878013 0-1.87572-0.119727-3.711532-0.360204-5.509481L591.970868 168.58151c0.239454-1.795902 0.360204-3.632737 0.360204-5.509481 0-22.574135-18.302855-40.876989-40.874943-40.876989-9.301853 0-17.884322 3.113921-24.750707 8.343015L225.680461 326.598406zM859.567485 510.524392l91.952248-91.951225c11.495822-11.517311 11.576663-30.558993-0.13917-42.274826-11.795651-11.795651-30.636764-11.755742-42.273802-0.140193l-91.953272 91.953272-91.950202-91.953272c-11.639085-11.616572-30.479175-11.655458-42.275849 0.140193-11.715833 11.715833-11.633968 30.757514-0.13917 42.274826l91.952248 91.951225-91.952248 91.953272c-11.494799 11.515265-11.576663 30.556946 0.13917 42.272779 11.796674 11.796674 30.636764 11.756765 42.275849 0.140193l91.950202-91.951225 91.953272 91.951225c11.636015 11.617595 30.477129 11.657504 42.273802-0.140193 11.715833-11.714809 11.634991-30.757514 0.13917-42.272779L859.567485 510.524392z" p-id="33508"></path></svg>',
            danmuSvg: '<svg t="1608882313164" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9509" width="24" height="24"><path d="M512 1024a512 512 0 1 1 512-512 512 512 0 0 1-512 512z m0-950.857143a438.857143 438.857143 0 1 0 438.857143 438.857143A438.857143 438.857143 0 0 0 512 73.142857z" fill="#ffffff" p-id="9510"></path><path d="M330.118095 454.948571l-8.045714 76.556191h109.958095a1276.099048 1276.099048 0 0 1-8.533333 182.857143q-9.508571 46.08-82.651429 50.468571c-8.777143 0-22.674286 0-41.203809-2.194286l-12.921905-47.055238a380.830476 380.830476 0 0 0 42.422857 2.681905c27.794286 0 43.885714-9.020952 48.761905-26.819047a658.285714 658.285714 0 0 0 6.339048-115.809524H270.628571l15.116191-164.815238h92.647619v-73.142858h-102.4V292.571429h152.380952v161.645714z m136.777143-97.523809h67.047619a438.857143 438.857143 0 0 0-41.691428-69.729524l46.567619-14.872381A532.72381 532.72381 0 0 1 579.047619 341.333333l-35.84 16.091429h78.750476a697.782857 697.782857 0 0 0 40.228572-88.502857l48.761904 16.822857a524.921905 524.921905 0 0 1-38.034285 71.68h64.853333v222.598095h-111.420952v44.617143h132.87619v48.761905h-132.87619v97.523809h-49.980953v-97.523809h-129.706666v-48.761905h129.706666V580.266667h-109.470476zM512 448.609524h64.365714v-48.761905H512z m64.365714 89.234286v-46.811429H512v46.811429z m49.980953-137.508572v48.761905h66.31619v-48.761905z m66.31619 137.508572v-46.811429h-66.31619v46.811429z" fill="#ffffff" p-id="9511"></path></svg>',
            closeDanmuSvg: '<svg t="1608882241739" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8605" width="24" height="24"><path d="M320.766977 443.142477l-8.52197 80.447403h115.217044a1349.198402 1349.198402 0 0 1-8.86285 192.255659c-6.817577 32.383489-34.087883 50.109188-86.583222 52.836219-9.544607 0-23.861518 0-43.291611-2.045273l-13.635154-50.790946a416.894807 416.894807 0 0 0 44.314248 2.727031c29.315579 0 46.359521-9.203728 50.790945-27.952064a676.985353 676.985353 0 0 0 6.817577-121.693742H258.386152l14.657789-171.121171h97.150466V320.766977H263.840213V274.407457h159.87217v170.439414z m143.169108-102.263649h70.561918a486.774967 486.774967 0 0 0-43.973369-72.948069l48.745672-15.680426a511.318242 511.318242 0 0 1 42.268975 71.925433l-35.792277 16.703062h82.492676a743.797603 743.797603 0 0 0 42.268975-92.719041l51.131824 17.38482a496.319574 496.319574 0 0 1-41.587217 75.334221h68.175766v233.501998h-117.262317v46.700399h139.419441v50.109188h-139.419441v102.263648h-51.131824v-102.263648h-136.351531v-49.086551h136.351531v-46.7004h-115.898802z m47.723036 96.809587h68.175766v-50.790945h-68.175766z m68.175766 93.400799V482.002663h-68.175766v49.086551z m52.154461-144.191744v50.790945h69.880159v-50.790945z m69.880159 144.191744V482.002663h-70.902796v49.086551z" fill="#ffffff" p-id="8606"></path><path d="M511.659121 83.174434A429.507324 429.507324 0 1 1 81.810919 511.318242 429.848202 429.848202 0 0 1 511.659121 83.174434m0-83.174434a511.318242 511.318242 0 1 0 511.318243 511.318242 511.318242 511.318242 0 0 0-511.318243-511.318242z" fill="#ffffff" p-id="8607"></path><path d="M148.964048 208.208788L206.811185 150.327563l666.929428 666.963516-57.847138 57.847137z" fill="#ffffff" p-id="8608"></path></svg>',
            autoRotateSvg: '<svg t="1609056405681" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2487" width="24" height="24"><path d="M752.5 860.5l57.1-0.9 0.9 58.7-176.1 2.7v-3.4c-1.7 0.5-3.4 0.9-5.1 1.3v-61.5c0.8-0.3 1.6-0.5 2.5-0.7l-0.2-117.7 58.7-0.1 0.1 91.2c125.1-70.4 197.1-207.8 183.9-350.7-13.2-142.9-109.2-264.7-245-311.1V107C786 152.3 902.7 283.7 929 444.8c26.4 161-42.3 322.8-176.5 415.7zM394.4 107.2v61.3l-0.9 0.3-1.6 121.1-56.3-0.9 1.2-95.3C210.2 263 136.6 400.6 149 544.4 161.5 688.2 257.7 811 394.3 857.6v61.5C236.2 873.4 118.9 739.9 94 577.1c-25-162.8 46.9-325.3 184.2-416.3h-71.6v-58.7h131.6v-0.1l7.1 0.1h37.4v0.6l11.7 0.2v4.3zM283.4 525l241.3-240.3c8.8-8.8 20.8-13.7 33.2-13.7 12.5 0 24.4 5 33.2 13.8l149.1 149.8c8.8 8.8 13.7 20.8 13.7 33.2 0 12.5-5 24.4-13.8 33.2L498.9 741.4c-8.8 8.8-20.8 13.7-33.2 13.7-12.5 0-24.4-5-33.2-13.8L283.3 591.5c-8.8-8.8-13.7-20.8-13.7-33.2 0-12.6 5-24.5 13.8-33.3z m176.3 182l244.9-244.8-143.7-143.7L316 563.3 459.7 707z m0 0" fill="#ffffff" p-id="2488"></path></svg>',
            f5Svg: '<svg t="1609563609897" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2493" width="18" height="18"><path d="M968.604 366.465H762.475c-26.297 0-47.567-21.306-47.567-47.57 0-26.26 21.271-47.567 47.567-47.567h82.748C770.58 165.856 647.837 96.912 508.776 96.912c-227.685 0-412.26 184.576-412.26 412.257 0 227.685 184.576 412.26 412.26 412.26 227.685 0 412.26-184.577 412.26-412.26 0-26.26 21.27-47.567 47.566-47.567 26.263 0 47.57 21.307 47.57 47.567 0 280.226-227.191 507.397-507.396 507.397-280.21 0-507.398-227.17-507.398-507.397 0-280.224 227.189-507.395 507.398-507.395 170.062 0 320.27 83.846 412.259 212.306v-85.457c0-26.263 21.27-47.568 47.566-47.568 26.263 0 47.57 21.305 47.57 47.568v190.273c0.004 26.263-21.307 47.57-47.567 47.57z" p-id="2494" fill="#ffffff"></path></svg>',
        },
        startGyro: function (callback) {
            window.addEventListener("deviceorientation", orientationHandler, false);

            function orientationHandler(event) {
                callback(event);
            }
        },
        stereoEffect: function (renderer) {

            // API
            /*Angle of deviation*/
            this.separation = 1;
            let that = this

            /*
             * Distance to the non-parallax or projection plane
             */
            this.focalLength = 15;

            // internals

            var _width, _height;

            var _position = new THREE.Vector3();
            var _quaternion = new THREE.Quaternion();
            var _scale = new THREE.Vector3();

            var _cameraL = new THREE.PerspectiveCamera();
            var _cameraR = new THREE.PerspectiveCamera();

            var _fov;
            var _outer, _inner, _top, _bottom;
            var _ndfl, _halfFocalWidth, _halfFocalHeight;
            var _innerFactor, _outerFactor;

            // initialization

            renderer.autoClear = false;

            this.setSize = function (width, height) {

                _width = width;
                _height = height;

                renderer.setSize(width, height);

            };

            this.render = function (scene, camera) {

                scene.updateMatrixWorld();

                void 0 === camera.parent && camera.updateMatrixWorld();

                camera.matrixWorld.decompose(_position, _quaternion, _scale);

                // Stereo frustum calculation

                // Effective fov of the camera
                _fov = THREE.Math.radToDeg(2 * Math.atan(Math.tan(THREE.Math.degToRad(camera.fov) * 0.5)));

                _ndfl = camera.near / this.focalLength;
                _halfFocalHeight = Math.tan(THREE.Math.degToRad(_fov) * 0.5) * this.focalLength;
                _halfFocalWidth = _halfFocalHeight * 0.5 * camera.aspect;

                _top = _halfFocalHeight * _ndfl;
                _bottom = -_top;
                _innerFactor = (_halfFocalWidth + this.separation / 2.0) / (_halfFocalWidth * 2.0);
                _outerFactor = 1.0 - _innerFactor;

                _outer = _halfFocalWidth * 2.0 * _ndfl * _outerFactor;
                _inner = _halfFocalWidth * 2.0 * _ndfl * _innerFactor;

                // left

                _cameraL.projectionMatrix.makePerspective(
                    -_outer,
                    _inner,
                    _top,
                    _bottom,
                    camera.near,
                    camera.far
                );

                _cameraL.position.copy(_position);
                _cameraL.quaternion.copy(_quaternion);


                // right

                _cameraR.projectionMatrix.makePerspective(
                    -_inner,
                    _outer,
                    _top,
                    _bottom,
                    camera.near,
                    camera.far
                );

                _cameraR.position.copy(_position);
                _cameraR.quaternion.copy(_quaternion);



                if (!that.isMobileDevice() || (that.isCrossScreen() && that.isMobileDevice())) {
                    _cameraL.translateX(-this.separation / 2.0);
                    _cameraR.translateX(this.separation / 2.0);
                    renderer.setViewport(0, 0, _width, _height);
                    //renderer.clear();

                    renderer.setViewport(0, 0, _width / 2, _height);
                    renderer.render(scene, _cameraL);

                    renderer.setViewport(_width / 2, 0, _width / 2, _height);
                    renderer.render(scene, _cameraR);
                } else {
                    _cameraL.translateY(-this.separation / 2.0);
                    _cameraR.translateY(this.separation / 2.0);
                    renderer.setViewport(0, 0, _width, _height);
                    //renderer.clear();

                    renderer.setViewport(0, 0, _width, _height / 2);
                    renderer.render(scene, _cameraL);

                    renderer.setViewport(0, _height / 2, _width, _height / 2);
                    renderer.render(scene, _cameraR);
                }


            };
            return this;
        },
        orbitControls: function (object, domElement) {
            var controls = function (object, domElement) {

                this.domElement = (void 0 !== domElement) ? domElement : document;
                this.object = object;
                this.object.rotation.reorder('YXZ');

                this.enable = !0;

                this.target = new THREE.Vector3();

                // How far you can orbit vertically, upper and lower limits.
                // Range is 0 to Math.PI radians.
                this.minPolarAngle = 0; // radians
                this.maxPolarAngle = Math.PI; // radians

                // How far you can orbit horizontally, upper and lower limits.
                // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
                this.minAzimuthAngle = -Infinity; // radians
                this.maxAzimuthAngle = Infinity; // radians

                // Set to true to enable damping (inertia)
                // If damping is enabled, you must call controls.update() in your animation loop
                this.enableDamping = !1;
                this.dampingFactor = 0.05;

                this.rotateSpeed = 0.25;

                // Set to true to automatically rotate around the target
                // If auto-rotate is enabled, you must call controls.update() in your animation loop
                this.autoRotate = !1;
                this.autoRotateSpeed = -0.8; // 30 seconds per round when fps is 60

                this.deviceOrientation = {};
                this.screenOrientation = 0;

                var scope = this;

                scope.defaultDirectionOfRotation = !0;
                scope.gyroEnable = !1;
                scope.usingGyro = AVR.OS.isMobile() ? !0 : !1;
                scope._defaultTargetY = scope.target.y;
                scope._defaultCameraFov = scope.object.fov;
                scope._defaultCameraY = scope.object.position.y;
                var changeEvent = {
                    type: 'change'
                };
                var startEvent = {
                    type: 'start'
                };
                var endEvent = {
                    type: 'end'
                };

                var EPS = 0.000001;

                var isFirst = true;
                // current position in spherical coordinates
                var spherical = new THREE.Spherical();
                var sphericalDelta = new THREE.Spherical();

                var rotateStart = new THREE.Vector2();
                var rotateEnd = new THREE.Vector2();
                var rotateDelta = new THREE.Vector2();
                var rotateOffsetDelta = new THREE.Vector3(0, 0, 0);

                var lastGamma = 0,
                    lastBeta = 0;

                var tempAlpha = 0,
                    tempBeta = 0,
                    tempGamma = 0;

                this.target0 = this.target.clone();
                this.position0 = this.object.position.clone();
                this.rotation0 = this.object.rotation.clone();
                this.zoom0 = this.object.zoom;
                //
                // public methods
                //
                this.arrowLeft = 37;
                this.arrowUp = 38;
                this.arrowRight = 39;
                this.arrowDown = 40;
                this.arrowSpeed = 0.05;


                this.getPolarAngle = function () {

                    return spherical.phi;

                };

                this.getAzimuthalAngle = function () {

                    return spherical.theta;

                };

                this.saveState = function () {

                    scope.target0.copy(scope.target);
                    scope.position0.copy(scope.object.position);
                    scope.rotation0.copy(scope.object.rotation);
                    scope.zoom0 = scope.object.zoom;

                };

                this.reset = function (config) {

                    this.resetVar();
                    scope.dispatchEvent(changeEvent);
                    (config && config.target0) ? scope.target.copy(config.target0) : scope.target.copy(scope.target0);
                    (config && config.position0) ? scope.object.position.copy(config.position0) : scope.object.position.copy(scope.position0);
                    (config && config.rotation0) ? scope.object.rotation.copy(config.rotation0) : scope.object.rotation.copy(scope.rotation0);
                    (config && config.zoom0) ? (scope.zoom = zoom0) : scope.zoom0;

                };
                this.resetVar = function () {
                    tempAlpha = 0;
                    tempBeta = 0;
                    tempGamma = 0;
                    lastGamma = 0;
                    lastBeta = 0;
                }
                var setObjectQuaternion = function () {
                    var zee = new THREE.Vector3(0, 0, 1);
                    var euler = new THREE.Euler();
                    var q0 = new THREE.Quaternion();
                    // - PI/2 around the x-axis
                    var q1 = new THREE.Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));

                    //beta=beta-180;
                    return function (quaternion, alpha, beta, gamma, orient) {
                        // 'ZXY' for the device, but 'YXZ' for us
                        euler.set(beta, alpha, -gamma, 'YXZ');
                        // orient the device
                        quaternion.setFromEuler(euler);
                        // camera looks out the back of the device, not the top
                        quaternion.multiply(q1);
                        // adjust for screen orientation
                        quaternion.multiply(q0.setFromAxisAngle(zee, -orient));
                    }
                }();

                // this method is exposed, but perhaps it would be better if we can make it private...
                this.update = function () {

                    var offset = new THREE.Vector3();

                    // so camera.up is the orbit axis

                    var quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));
                    var quatInverse = quat.clone().inverse();

                    var lastPosition = new THREE.Vector3();
                    var lastQuaternion = new THREE.Quaternion();

                    return function update(param) {
                        if (!scope.enable) {
                            return;
                        }
                        param = param || {};

                        var alpha = scope.deviceOrientation.alpha ? THREE.Math.degToRad(void 0 === scope.beginAlpha ? scope.deviceOrientation.alpha : scope.deviceOrientation.alpha - scope.beginAlpha) : 0; // Z
                        var beta = scope.deviceOrientation.beta ? THREE.Math.degToRad(scope.deviceOrientation.beta) : 0; // X'
                        var gamma = scope.deviceOrientation.gamma ? THREE.Math.degToRad(scope.deviceOrientation.gamma) : 0; // Y''
                        var orient = scope.screenOrientation ? THREE.Math.degToRad(scope.screenOrientation) : 0; // O
                        if (scope.gyroEnable) {
                            tempAlpha = alpha, tempBeta = beta, tempGamma = gamma;
                        } else {
                            alpha = tempAlpha, beta = tempBeta, gamma = tempGamma;
                        }

                        var currentQ = new THREE.Quaternion().copy(scope.object.quaternion);

                        setObjectQuaternion(currentQ, alpha, beta, gamma, orient);

                        var currentAngle = Quat2Angle(currentQ.x, currentQ.y, currentQ.z, currentQ.w);
                        if (!param.init) {
                            // currentAngle.z = Left-right
                            // currentAngle.y = Up-down
                            rotateLeft((lastGamma - currentAngle.z));
                            //rotateUp((lastBeta - currentAngle.y));
                        }

                        lastBeta = currentAngle.y;
                        lastGamma = currentAngle.z;
                        var position = scope.object.position;

                        offset.copy(position).sub(scope.target);

                        // rotate offset to "y-axis-is-up" space
                        offset.applyQuaternion(quat);

                        // angle from z-axis around y-axis
                        spherical.setFromVector3(offset);

                        if (scope.autoRotate) {
                            rotateLeft(getAutoRotationAngle());
                        }

                        spherical.theta += sphericalDelta.theta;
                        spherical.phi += sphericalDelta.phi;

                        // restrict theta to be between desired limits
                        spherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta));

                        // restrict phi to be between desired limits
                        spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));

                        spherical.makeSafe();
                        offset.setFromSpherical(spherical);

                        // rotate offset back to "camera-up-vector-is-up" space
                        offset.applyQuaternion(quatInverse);

                        position.copy(scope.target).add(offset);
                        if (scope.deviceOrientation && scope.gyroEnable) {
                            setObjectQuaternion(scope.object.quaternion, alpha + Math.PI + rotateOffsetDelta.x, beta + rotateOffsetDelta.y, gamma + rotateOffsetDelta.z, orient);
                            //return true;
                        } else {
                            scope.object.lookAt(scope.target);
                        }
                        if (scope.enableDamping && !scope.gyroEnable) {
                            sphericalDelta.theta *= (1 - scope.dampingFactor);
                            sphericalDelta.phi *= (1 - scope.dampingFactor);
                        } else {
                            sphericalDelta.set(0, 0, 0);
                        }

                        // update condition is:
                        // min(camera displacement, camera rotation in radians)^2 > EPS
                        // using small-angle approximation cos(x/2) = 1 - x^2 / 8

                        if (lastPosition.distanceToSquared(scope.object.position) > EPS ||
                            8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {

                            scope.dispatchEvent(changeEvent);

                            lastPosition.copy(scope.object.position);
                            lastQuaternion.copy(scope.object.quaternion);

                            return true;
                        }
                        return false;
                    };
                }();

                function getAutoRotationAngle() {

                    return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;

                }

                function rotateLeft(angle) {
                    if (scope.defaultDirectionOfRotation) {
                        if (scope.usingGyro) {
                            sphericalDelta.theta -= angle;
                        } else {
                            sphericalDelta.theta += angle;
                        }
                    } else {
                        sphericalDelta.theta -= angle;
                    }
                }

                function rotateUp(angle) {
                    if (scope.defaultDirectionOfRotation) {
                        if (scope.usingGyro) {
                            sphericalDelta.phi -= angle;
                        } else {
                            sphericalDelta.phi += angle;
                        }
                    } else {
                        sphericalDelta.phi -= angle;
                    }
                }

                function Quat2Angle(x, y, z, w) {
                    var pitch, roll, yaw;

                    var test = x * y + z * w;
                    if (test > 0.499) { // singularity at north pole
                        yaw = 2 * Math.atan2(x, w);
                        pitch = Math.PI / 2;
                        roll = 0;

                        var euler = new THREE.Vector3(pitch, roll, yaw);
                        return euler;
                    }

                    if (test < -0.499) { // singularity at south pole
                        yaw = -2 * Math.atan2(x, w);
                        pitch = -Math.PI / 2;
                        roll = 0;
                        var euler = new THREE.Vector3(pitch, roll, yaw);
                        return euler;
                    }

                    var sqx = x * x;
                    var sqy = y * y;
                    var sqz = z * z;

                    yaw = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz);
                    pitch = Math.asin(2 * test);
                    roll = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz);
                    var euler = new THREE.Vector3(pitch, roll, yaw);
                    return euler;
                }

                function calcDeltaLeft(x, clientWidth) {
                    return 2 * Math.PI * x / clientWidth * scope.rotateSpeed
                }

                function calcDeltaUp(y, clientHeight) {
                    return 2 * Math.PI * y / clientHeight * scope.rotateSpeed
                }
                var mouseDown = false;

                function mousedown(e) {
                    mouseDown = true;
                    var x = e.clientX || e.changedTouches[0].clientX;
                    var y = e.clientY || e.changedTouches[0].clientY;
                    rotateStart.set(x, y);
                }

                function mousemove(e) {

                    var x = e.clientX || e.changedTouches[0].clientX;
                    var y = e.clientY || e.changedTouches[0].clientY;
                    rotateEnd.set(x, y);
                    rotateDelta.subVectors(rotateEnd, rotateStart);

                    // rotating across whole screen goes 360 degrees around
                    var clientWidth = (void 0 !== scope.domElement.clientWidth) ? scope.domElement.clientWidth : window.innerWidth;
                    rotateLeft(calcDeltaLeft(rotateDelta.x, clientWidth));

                    // rotating up and down along whole screen attempts to go 360, but limited to 180
                    var clientHeight = (void 0 !== scope.domElement.clientHeight) ? scope.domElement.clientHeight : window.innerHeight;
                    rotateUp(calcDeltaUp(rotateDelta.y, clientHeight));

                    rotateStart.copy(rotateEnd);
                }

                function mouseup(event) {
                    mouseDown = !1;
                }

                function touchstart(event) {
                    //console.log( 'handleTouchStartRotate' );
                    mouseDown = !0;
                    rotateStart.set(event.touches[0].pageX, event.touches[0].pageY);
                    scope.usingGyro = !1;
                }

                function touchmove(event) {
                    //console.log( 'handleTouchMoveRotate' );

                    event.preventDefault();

                    rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
                    rotateDelta.subVectors(rotateEnd, rotateStart);

                    // rotating across whole screen goes 360 degrees around
                    var clientWidth = (void 0 != scope.domElement.clientWidth) ? scope.domElement.clientWidth : window.innerWidth;
                    rotateLeft(calcDeltaLeft(rotateDelta.x, clientWidth));

                    // rotating up and down along whole screen attempts to go 360, but limited to 180
                    var clientHeight = (void 0 !== scope.domElement.clientHeight) ? scope.domElement.clientHeight : window.innerHeight;
                    rotateUp(calcDeltaUp(rotateDelta.y, clientHeight));

                    rotateStart.copy(rotateEnd);
                    rotateOffsetDelta.x += calcDeltaLeft(rotateDelta.x, clientWidth) + calcDeltaUp(rotateDelta.y, clientHeight);
                    scope.usingGyro = !1;
                }

                function touchend(event) {
                    //console.log( 'handleTouchEnd' );
                    scope.usingGyro = AVR.OS.isMobile() ? !0 : !1;
                    mouseDown = false;
                }

                function deviceorientation(event) {
                    scope.deviceOrientation = event;
                    void 0 === scope.beginAlpha && (scope.beginAlpha = scope.deviceOrientation.alpha);
                }

                function orientationchange(event) {
                    scope.screenOrientation = window.orientation || 0;
                }

                var devices = null;
                if (typeof DeviceMotionEvent !== 'undefined') {
                    devices = DeviceMotionEvent;
                }
                if (typeof DeviceOrientationEvent !== 'undefined') {
                    devices = DeviceOrientationEvent;
                }
                window.addEventListener('orientationchange', orientationchange, false);
                window.addEventListener('deviceorientation', deviceorientation, false);
                if (devices && typeof devices.requestPermission === 'function') {
                    window.addEventListener('click', function () {
                        devices.requestPermission()
                            .then(function (permissionState) {
                                if (permissionState === 'granted') {
                                    window.addEventListener('devicemotion', orientationchange, false);
                                    window.addEventListener('deviceorientation', deviceorientation, false);
                                }
                            })
                            .catch(function (err) {
                                AVR.msgBox(err, 3, document.body);
                            })
                    })
                } else {
                    // handle regular non iOS 13+ devices
                }
                this.gyroFreeze = function () {
                    scope.gyroEnable = false;
                };
                this.gyroUnfreeze = function () {
                    scope.gyroEnable = true;
                };
                this.rotationLeft = rotateLeft;
                this.rotationUp = rotateUp;

                var _up = 0;
                var _left = 0;
                document.addEventListener('keydown', function (event) {
                    var e = event || window.event || arguments.callee.caller.arguments[0];
                    if (!e) {
                        return;
                    }
                    if (e.keyCode == scope.arrowLeft) { // 按左箭头 
                        _left = 1
                    }
                    if (e.keyCode == scope.arrowRight) {
                        _left = -1;
                    }
                    if (e.keyCode == scope.arrowUp) {
                        _up = 1;
                    }
                    if (e.keyCode == scope.arrowDown) {
                        _up = -1;
                    }
                    rotateLeft(_left * scope.arrowSpeed);
                    rotateUp(_up * scope.arrowSpeed);
                })
                document.addEventListener('keyup', function (event) {
                    var e = event || window.event || arguments.callee.caller.arguments[0];
                    if (!e) {
                        return;
                    }
                    if (e.keyCode == scope.arrowLeft) { // 按左箭头 
                        _left = 0
                    }
                    if (e.keyCode == scope.arrowRight) {
                        _left = 0;
                    }
                    if (e.keyCode == scope.arrowUp) {
                        _up = 0;
                    }
                    if (e.keyCode == scope.arrowDown) {
                        _up = 0;
                    }
                })

                this.domElement.addEventListener("mousedown", mousedown, false);
                this.domElement.addEventListener('mousemove', function (e) {
                    if (scope.enable && mouseDown) {
                        mousemove(e);
                    }
                }, false);
                this.domElement.addEventListener("mouseup", mouseup, false);
                this.domElement.addEventListener("mouseleave", mouseup, false);
                this.domElement.addEventListener('touchstart', touchstart, false);
                this.domElement.addEventListener('touchend', touchend, false);
                this.domElement.addEventListener('touchmove', touchmove, false);

                // set mousemove base point is dom center
                var clientWidth = (void 0 !== this.domElement.clientWidth) ? this.domElement.clientWidth : window.innerWidth;
                var clientHeight = (void 0 !== this.domElement.clientHeight) ? this.domElement.clientHeight : window.innerHeight;
                rotateStart.set(clientWidth / 2, clientHeight / 2);

                // force an update at start
                //rotateLeft(THREE.Math.degToRad(-180));
                setTimeout(function () {
                    //scope.enable = true;
                    scope.update({
                        init: true
                    });
                    scope.saveState();
                }, 10);
                return this;
            }
            controls.prototype = Object.create(THREE.EventDispatcher.prototype);
            controls.prototype.constructor = controls;
            return new controls(object, domElement);
        },
        setCameraPara: function (that, cameraPara, cameraPosition) {
            that.cameraPara = {
                "fov": 90,
                "aspect": that.container.innerWidth / that.container.innerHeight,
                "near": 0.001,
                "far": 1000
            };
            that.cameraPosition = {
                "x": 0,
                "y": 0,
                "z": 0
            };
            if (cameraPara) {
                for (var property in cameraPara) {
                    that.cameraPara[property] = cameraPara[property];
                }
            }
            if (cameraPosition) {
                for (var property in cameraPosition) {
                    that.cameraPosition[property] = cameraPosition[property];
                }
            }
        },
        formatSeconds: function (value) {
            var theTime = parseInt(value); // 秒
            if (!theTime) {
                return '00:00';
            }
            var theTime1 = 0; // 分
            var theTime2 = 0; // 小时
            if (theTime > 60) {
                theTime1 = parseInt(theTime / 60);
                theTime = parseInt(theTime % 60);
                if (theTime1 > 60) {
                    theTime2 = parseInt(theTime1 / 60);
                    theTime1 = parseInt(theTime1 % 60);
                }
            }
            var result = "" + ((parseInt(theTime) < 10) ? "0" + parseInt(theTime) : parseInt(theTime));
            if (theTime1 >= 0 && theTime2 > 0) {
                result = ((parseInt(theTime2) < 10) ? "0" + parseInt(theTime2) : parseInt(theTime2)) + ":" + ((parseInt(theTime1) < 10) ? "0" + parseInt(theTime1) : parseInt(theTime1)) + ":" + result;
            } else if (theTime1 > 0 && theTime2 == 0) {
                if (theTime1 == 60) {
                    result = "01:00:" + result;
                } else {
                    result = ((parseInt(theTime1) < 10) ? "0" + parseInt(theTime1) : parseInt(theTime1)) + ":" + result;
                }

            } else {
                if (theTime == 60) {
                    result = "01:00";
                } else {
                    result = "00:" + result;
                }
            }
            return result;
        },
        cameraVector: function (camera, times) {
            var vector = new THREE.Vector3(0, 0, -1);
            var lookAt = vector.applyQuaternion(camera.quaternion);
            var lookAtVector = lookAt.clone();
            var timesVector = new THREE.Vector3();
            if (times) {
                timesVector.x = lookAt.x * times;
                timesVector.y = lookAt.y * times;
                timesVector.z = lookAt.z * times;
            }
            return {
                'vector': lookAtVector,
                'timesVector': timesVector
            };
        },
        bindRaycaster: function (event, vr, callback) {

            var vector = AVR.screenPosTo3DCoordinate(event, vr.container, vr.camera);
            //在视点坐标系中形成射线,射线的起点向量是照相机， 射线的方向向量是照相机到点击的点，这个向量应该归一标准化。
            var raycaster = new THREE.Raycaster(vr.camera.position, vector.sub(vr.camera.position).normalize());

            //射线和模型求交，选中一系列直线
            var intersects = raycaster.intersectObjects(vr.scene.children, true);

            if (intersects.length) {
                callback.success(intersects);
            } else {
                callback.empty();
            }
        },
        bindCameraEvent: function (vr, options) {
            options = options || {
                trigger: function (e) { },
                empty: function (e) { },
                move: function (e) { }
            };
            var that = this;
            var scale = options.scale || 0.022;
            var vectorRadius = options.vectorRadius;
            var radius = vectorRadius * scale;
            var tube = vectorRadius * (scale / 6);
            var pointSize = vectorRadius * (scale / 8);
            var radialSegments = 2;
            var tubularSegments = options.tubularSegments || 60;
            var speed = options.speed || 36;
            var ControlGroup = new THREE.Group();
            ControlGroup.name = "__controlHandle";

            var waitGeometry = new THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, 2 * Math.PI);
            var waitMaterial = [];
            for (var i = 0; i < waitGeometry.faces.length / 2; i++) {
                waitMaterial[i] = new THREE.MeshBasicMaterial({
                    color: 0xe7dada,
                    depthTest: false
                });
            }
            var faceId = 0;
            var uv = [new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1)];
            for (var i = 0, l = waitGeometry.faces.length; i < l; i += 2) {
                waitGeometry.faces[i].materialIndex = faceId;
                waitGeometry.faces[i + 1].materialIndex = faceId;
                waitGeometry.faceVertexUvs[0][i] = [uv[3], uv[0], uv[2]];
                waitGeometry.faceVertexUvs[0][i + 1] = [uv[0], uv[1], uv[2]];
                faceId++;
            }
            var wait = new THREE.Mesh(waitGeometry, waitMaterial);
            //wait.lookAt(vr.camera.position)
            wait.name = "__wait";
            wait.visible = false;
            ControlGroup.add(wait);

            var cameraPointer = new THREE.Mesh(new THREE.CircleGeometry(tube, 4), new THREE.MeshBasicMaterial({
                color: 0xe7dada,
                wireframe: true,
                depthTest: false
            }));
            cameraPointer.lookAt(vr.camera.position);
            cameraPointer.name = "__focus";
            cameraPointer.material.depthTest = false;
            cameraPointer.visible = false;
            ControlGroup.add(cameraPointer);
            ControlGroup.position.set(0, 0, 0.1)
            var timer = null;
            var lastCameraVector = new THREE.Vector3();


            var updatePosition = function () {
                ControlGroup.lookAt(0, 0, 0);
                wait.lookAt(0, 0, 0);
                var v = that.cameraVector(vr.camera, vectorRadius);
                cameraPointer.visible = true;
                ControlGroup.position.set(v.timesVector.x, v.timesVector.y, v.timesVector.z);
                //在视点坐标系中形成射线,射线的起点向量是照相机， 射线的方向向量是照相机到点击的点，这个向量应该归一标准化。
                var raycaster = new THREE.Raycaster(vr.camera.position, v.vector);

                //射线和模型求交，选中一系列直线
                var intersects = raycaster.intersectObjects(vr.scene.children, true);
                if (intersects.length) {
                    options.move(intersects);
                } else {
                    options.empty(intersects);
                }
            }
            var Ctimer = null;
            var hover = function (e) {
                wait.visible = true;
                var offset = 0;
                var mIndex = 0;
                if (!Ctimer) {
                    Ctimer = setInterval(function () {
                        if (mIndex < waitGeometry.faces.length / 4) {
                            waitMaterial[mIndex].color = new THREE.Color(0xe07575)
                            waitGeometry.needsUpdate = true;
                            waitGeometry.faces[offset].materialIndex = mIndex;
                            waitGeometry.faces[offset + 1].materialIndex = mIndex;
                            waitGeometry.faceVertexUvs[0][offset] = [uv[3], uv[0], uv[2]];
                            waitGeometry.faceVertexUvs[0][offset + 1] = [uv[0], uv[1], uv[2]];
                            offset += 2;
                        } else {
                            clearInterval(Ctimer);
                            Ctimer = null;
                            options.trigger(e);
                        }
                        mIndex++;
                    }, speed);
                }
            }
            var leave = function (e) {
                clearInterval(Ctimer);
                Ctimer = null;
                faceId = 0;
                for (var i = 0, l = waitGeometry.faces.length; i < l; i += 2) {
                    waitMaterial[faceId].color = new THREE.Color(0xe7dada)
                    waitGeometry.needsUpdate = true;
                    waitGeometry.faces[i].materialIndex = faceId;
                    waitGeometry.faces[i + 1].materialIndex = faceId;
                    waitGeometry.faceVertexUvs[0][i] = [uv[3], uv[0], uv[2]];
                    waitGeometry.faceVertexUvs[0][i + 1] = [uv[0], uv[1], uv[2]];
                    faceId++;
                }
                wait.visible = false;
            }
            vr.VRObject.add(ControlGroup);
            vr.cameraEvt.controlGroup = ControlGroup;
            vr.cameraEvt.updatePosition = updatePosition;
            vr.cameraEvt.hover = hover;
            vr.cameraEvt.leave = leave;
            //vr.cameraEvt={'controlGroup':ControlGroup,'updatePosition':updatePosition,'hover':hover,'leave':leave};
        },
        screenPosTo3DCoordinate: function (e, container, camera) {
            var clientX = e.clientX || (e.touches ? e.touches[0].clientX : 0);
            var clientY = e.clientY || (e.touches ? e.touches[0].clientY : 0);
            rect = AVR.getBoundingClientRect(container);
            x = clientX - rect.left;
            y = clientY - rect.top;
            //console.log(x, y);
            var W = container.clientWidth;
            var H = container.clientHeight;
            var mouse = new THREE.Vector2();
            mouse.x = 2 * x / W - 1;
            mouse.y = 1 - 2 * y / H;
            var vector = new THREE.Vector3(mouse.x, mouse.y, 0).unproject(camera);
            return vector.sub(camera.position).normalize();
            //return vector;
        },
        objectPosToScreenPos: function (object, container, camera) {
            var vector = new THREE.Vector3();
            vector.setFromMatrixPosition(object.matrixWorld).project(camera);
            var x2hat = vector.x,
                y2hat = vector.y;
            var W = container.clientWidth;
            var H = container.clientHeight;
            var pos = new THREE.Vector2();
            pos.x = (W / 2) * (x2hat + 1);
            pos.y = (H / 2) * (1 - y2hat);
            return pos;
        },
        fullscreen: function (el, flag) {
            var isFullscreen = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen || false;

            if (!isFullscreen) { //进入全屏,多重短路表达式

                (el.requestFullscreen && el.requestFullscreen()) ||
                    (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
                    (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) || (el.msRequestFullscreen && el.msRequestFullscreen());

            } else { //退出全屏,三目运算符
                document.exitFullscreen ? document.exitFullscreen() :
                    document.mozCancelFullScreen ? document.mozCancelFullScreen() :
                        document.webkitExitFullscreen ? document.webkitExitFullscreen() : '';

            }
            if (flag) {
                el.style.position = 'fixed'
                el.style.zIndex = '10000'
            }
            else {
                el.style.position = 'absolute'
                el.style.zIndex = '0'
            }
        },
        isFullscreen: function () {
            return document.fullscreenElement ||
                document.msFullscreenElement ||
                document.mozFullScreenElement ||
                document.webkitFullscreenElement || false;
        },
        toolBar: function (container, playUrlArray, isLive) {
            var pre = "_toolBar";
            var toolbar = this.createTag('div', {
                'style': 'z-index:-1;-moz-user-select:none;-webkit-user-select:none;user-select:none;position:absolute;background:rgba(0,0,0,.2);width:100%;height:2.4rem;bottom:0rem;',
                'class': pre + 'Area'
            });

            var btn = this.createTag('div', {
                'style': 'position:inherit;left:0.5rem;color:#fff;cursor:pointer;bottom:0rem;line-height:100%;',
                'class': pre + 'Btn'
            }, {
                'innerHTML': AVR.playerIcon.playSvg,
            });

            toolbar.appendChild(btn);

            var rightControl = this.createTag('div', {
                'style': 'height:100%;position:inherit;right:0;display: flex;align-items: center;padding-top: 0.3rem;',
                'class': 'right-control'
            });
            toolbar.appendChild(rightControl);

            var tt = document.styleSheets[0];
            tt.insertRule("@keyframes moreTip{from {top:0.75rem;} to{top:1rem}}", 0); //写入样式
            if (!AVR.Broswer.isIE()) {
                tt.insertRule("@-webkit-keyframes moreTip{from {top:0.75rem;} to{top:1rem}}", 0); //写入样式
            }

            var gyroBtn = this.createTag('div', {
                'style': 'cursor:pointer;margin-right: 10px;display: flex;align-items: center;justify-content: center;'
            }, {
                innerHTML: AVR.playerIcon.gyroSvg,
            });


            var vrBtn = this.createTag('div', {
                'style': "cursor:pointer;margin-right: 10px;display: flex;align-items: center;justify-content: center;"
            }, {
                'innerHTML': AVR.playerIcon.vrSvg
            });
            var fullScreenBtn = this.createTag('div', {
                'style': "cursor:pointer;margin-right: 10px;display: flex;align-items: center;justify-content: center;"
            }, {
                'innerHTML': AVR.playerIcon.fullScreenSvg
            });
            // if (AVR.isMobileDevice()) {
            //     toolbar.appendChild(vrBtn);
            // } else {

            // }
            var progressBar = this.createTag('div', {
                'style': 'position:inherit;top:0rem;width:100%;height:0.2rem;background:rgba(255,255,255,.3);cursor:pointer;'
            });

            var loaded_progress = this.createTag('div', {
                'style': 'position:inherit;width:0%;height:0.2rem;background:rgba(255,255,255,.3)'
            });
            progressBar.appendChild(loaded_progress);
            var play_progress = this.createTag('div', {
                'style': 'position:inherit;width:0%;height:0.2rem;background:rgba(28, 175, 252,.6)'
            });
            progressBar.appendChild(play_progress);

            toolbar.appendChild(progressBar);

            container.appendChild(toolbar);

            var voice_bar = this.createTag('div', {
                'style': '-moz-user-select:none;-webkit-user-select:none;user-select:none;position:absolute;width:2rem;height:60%;background:rgba(0,0,0,0);left:0rem;top:20%;text-align:center;display:none;border-radius:1rem;'
            });
            var voice_slide_bar = this.createTag('div', {
                'style': 'position:inherit;width:0.25rem;background:rgba(255,255,255,.1);height:100%;left:0.875rem;cursor:pointer;border-radius:1rem;'
            });
            voice_bar.appendChild(voice_slide_bar);

            var voice_cur_slide = this.createTag('div', {
                'style': 'position:inherit;width:100%;background:rgba(255, 255, 255,.6);bottom:0rem;border-radius:1rem;transition: all .3s;'
            });
            voice_slide_bar.appendChild(voice_cur_slide);


            container.appendChild(voice_bar);

            var pictureQualityNum = 0
            var pictureQualityItem = []
            for (var item of playUrlArray) {
                pictureQualityNum++
                let _pictureQualityItem = this.createTag('div', {
                    'style': 'height:22px;text-align:center;line-height:22px;cursor:pointer;transition: all .3s;'
                }, {
                    'innerHTML': item.name
                });

                _pictureQualityItem.setAttribute('url', item.url)
                _pictureQualityItem.setAttribute('quality', item.name)
                _pictureQualityItem.addEventListener("mouseover", function () {
                    this.style.backgroundColor = 'rgba(0, 0, 0, 0.3)'
                })
                _pictureQualityItem.addEventListener("mouseout", function () {
                    this.style.backgroundColor = 'unset'
                })
                pictureQualityItem.push(_pictureQualityItem)
            }
            var pictureQualityBox = this.createTag('div', {
                'style': 'display:none;color:#fff;position:inherit;border-radius:4px;height:' + pictureQualityNum * 22 + 'px;width:60px;background:rgba(0, 0, 0, 0.2);right:57px;bottom:41px;'
            });

            for (var item of pictureQualityItem) {
                pictureQualityBox.appendChild(item)
            }
            if (isLive) {
                container.appendChild(pictureQualityBox);
            }
            var pictureQualityBtn = this.createTag('div', {
                'style': 'color:#fff;cursor:pointer;font-size: 14px;width: 28px;text-align: center;margin-right: 10px;display: flex;align-items: center;justify-content: center;'
            }, {
                innerHTML: playUrlArray[0].name,
            });


            var loaddingIcon = this.createTag('div', {
                'style': "color:#fff;display: none;align-items: center;justify-content: center;position:inherit;color:rgba(0, 0, 0, 0.2);width:40px;height:40px;left:50%;top:50%;margin-left:-20px;margin-top:-20px;",
                'class': 'rotation'
            }, {
                'innerHTML': AVR.playerIcon.loaddingSvg
            });
            container.appendChild(loaddingIcon);

            var danmuBtn = this.createTag('div', {
                'style': "color:#fff;cursor:pointer;font-size: 16px;margin-right: 10px;display: flex;align-items: center;justify-content: center;",
                'active': 'active'
            }, {
                'innerHTML': AVR.playerIcon.danmuSvg
            });

            var autoRotateBtn = this.createTag('div', {
                'style': "color:#fff;cursor:pointerfont-size: 16px;margin-right: 10px;display: flex;align-items: center;justify-content: center;",
                'active': 'active'
            }, {
                'innerHTML': AVR.playerIcon.autoRotateSvg
            });


            var beginBox = this.createTag('div', {
                'style': `cursor: pointer;;background:#000;display:none;position: absolute;width: 100%;height: 100%;left: 0px;top: 0px;overflow: hidden;align-items: center;justify-content: center;z-index: 1;`
            });
            var begin = this.createTag('img', {
                'style': `width: 270px;margin-top: -22px;`,
                'src': '/assets/images/begin-web.png'
            });

            beginBox.appendChild(begin);
            container.appendChild(beginBox);

            var f5Btn = this.createTag('div', {
                'style': "position:inherit;left:2.6rem;color:#fff;cursor:pointer;bottom:0.18rem;",
            }, {
                'innerHTML': AVR.playerIcon.f5Svg
            });
            var timeInfo = this.createTag('div', {
                'style': 'position:inherit;bottom:0.5rem;left:2.8rem;color:#fff;font-size:0.75rem'
            });
            var curTime = this.createTag('span', null, {
                'innerText': "00:00"
            });
            timeInfo.appendChild(curTime);
            var splitTime = this.createTag('span', null, {
                'innerText': '/'
            });
            timeInfo.appendChild(splitTime);

            var totalTime = this.createTag('span', null, {
                'innerText': '00:00'
            });
            timeInfo.appendChild(totalTime);
            if (isLive) {
                toolbar.appendChild(f5Btn);
            } else {
                toolbar.appendChild(timeInfo);
            }
            //右边按钮组
            rightControl.appendChild(autoRotateBtn);
            if (AVR.isMobileDevice()) {
                rightControl.appendChild(gyroBtn);
            }
            if (isLive) {
                rightControl.appendChild(danmuBtn);
                rightControl.appendChild(pictureQualityBtn);
            }
            // rightControl.appendChild(vrBtn);
            rightControl.appendChild(fullScreenBtn);
            return {
                'toolbar': toolbar,
                'btn': btn,
                'vrBtn': vrBtn,
                'progressBar': progressBar,
                'loadedProgress': loaded_progress,
                'playProgress': play_progress,
                'pictureQualityBtn': pictureQualityBtn,
                "voice_bar": voice_bar,
                'timeInfo': timeInfo,
                'curTime': curTime,
                'splitTime': splitTime,
                'totalTime': totalTime,
                "pictureQualityBox": pictureQualityBox,
                "loaddingIcon": loaddingIcon,
                "fullScreenBtn": fullScreenBtn,
                "gyroBtn": gyroBtn,
                "danmuBtn": danmuBtn,
                "beginBox": beginBox,
                "f5Btn": f5Btn,
                "autoRotateBtn": autoRotateBtn,
            };
        },
        msgBox: function (msg, timeout, container) {
            if (!msg) {
                return;
            }
            var msgbox = this.createTag('div', {
                'style': 'position:absolute;bottom:50%;width:100%;padding:0.25rem;background:rgba(0,0,0,.6);color:#fff;text-align:center;'
            }, {
                'innerHTML': msg
            });
            container.appendChild(msgbox);
            setTimeout(function () {
                msgbox.remove();
            }, timeout * 1000);
        },
        isMobileDevice: function (deviceType) {
            var sUserAgent = navigator.userAgent.toLowerCase();
            if (deviceType) {
                return (sUserAgent.match(/ipad/i) || sUserAgent.match(/iphone os/i) || sUserAgent.match(/midp/i) ||
                    sUserAgent.match(/rv:1.2.3.4/i) || sUserAgent.match(/ucweb/i) || sUserAgent.match(/android/i) ||
                    sUserAgent.match(/windows ce/i) || sUserAgent.match(/windows mobile/i))
            }

            var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
            var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
            var bIsMidp = sUserAgent.match(/midp/i) == "midp";
            var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
            var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
            var bIsAndroid = sUserAgent.match(/android/i) == "android";
            var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
            var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
            if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
                //dconsole.log("phone");
                return true;
            } else {
                //console.log("pc");
                return false;
            }
        },
        bindOrientationEvent: function (that) {
            if (void 0 === that.controls) {
                that.controls = AVR.orbitControls(that.camera, that.renderer.domElement);
                that.controls.target = that._controlTarget.clone();
            }
        },
        //横屏判断
        isCrossScreen: function (callback) {
            var that = this;
            if (window.orientation == 180 || window.orientation == 0) {
                /*Vertical screen*/
                return false;
            }
            if (window.orientation == 90 || window.orientation == -90) {
                /*is Cross Screen*/
                return true;
            }
        },
        initDomStyle: function (container) {
            document.body.style.overflow = "hidden";
            document.body.style.margin = 0;
            document.body.style.padding = 0;
            container.style.position = "absolute";
            container.style.width = "100%";
            container.style.height = "100%";
            container.style.left = "0px";
            container.style.top = "0px";
            container.style.overflow = "hidden";
            var style = document.createElement('style');
            document.getElementsByTagName('head')[0].appendChild(style);

            document.body.addEventListener("touchmove", bodyPreventDefault);
            document.oncontextmenu = function () {
                return false;
            };

            function bodyPreventDefault(e) {
                // e.preventDefault();
            }
            document.onkeydown = function () {
                if (!this.debug && window.event && window.event.keyCode == 123) {
                    event.keyCode = 0;
                    event.returnValue = false;
                    return false;
                }
            };
        },
        createTag: function (tag, attr, objs) {
            var oMeta = document.createElement(tag);
            if (attr && typeof attr === "object") {
                for (var k in attr) {
                    oMeta.setAttribute(k, attr[k]);
                }
            }
            if (objs && typeof objs === "object") {
                for (var k in objs) {
                    oMeta[k] = objs[k];
                }
            }
            return oMeta;
        },
        OS: {
            weixin: navigator.userAgent.indexOf('MicroMessenger') > -1,
            android: /android/i.test(navigator.userAgent.toLowerCase()),
            ios: /(iphone|ipad|ipod|ios)/i.test(navigator.userAgent.toLowerCase()),
            googlePixel: navigator.userAgent.match(/;\sPixel\sBuild\//),
            MiOS: navigator.userAgent.match(/;\sMI\s\d\sBuild\//),
            samsungOS: navigator.userAgent.match(/;\sSM\-\w+\sBuild\//),
            isGooglePixel: function () {
                return this.googlePixel != null;
            },
            isMiOS: function () {
                return this.MiOS != null;
            },
            isSamsung: function () {
                return this.samsungOS != null;
            },
            isMobile: function () {
                return this.android || this.ios;
            },

            isAndroid: function () {
                return this.android;
            },

            isiOS: function () {
                return this.ios;
            },

            isWeixin: function () {
                return this.weixin;
            }
        },
        Broswer: {
            win: window,
            nav: window.navigator,
            REG_APPLE: /^Apple/,
            ie: navigator.userAgent.match(/MSIE\s([\d.]+)/) || navigator.userAgent.match(/Trident\/[\d](?=[^\?]+).*rv:([0-9.].)/),
            edge: navigator.userAgent.match(/Edge\/([\d.]+)/),
            chrome: navigator.userAgent.match(/Chrome\/([\d.]+)/) || navigator.userAgent.match(/CriOS\/([\d.]+)/),
            webview: !this.chrome && navigator.userAgent.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/),
            safari: this.webview || navigator.userAgent.match(/Version\/([\d.]+)([^S](Safari)|[^M]*(Mobile)[^S]*(Safari))/),
            chromiumType: null,

            _getChromiumType: function () {
                if (this.chromiumType != null) {
                    return this.chromiumType;
                }

                var win = this.win;

                if (this.isIE() || void 0 === win.scrollMaxX || this.REG_APPLE.test(this.nav.vendor || '')) {
                    return '';
                }

                // 搜狗浏览器
                if (this._testExternal(/^sogou/i, 0)) {
                    return 'sogou';
                }

                // 猎豹浏览器
                if (this._testExternal(/^liebao/i, 0)) {
                    return 'liebao';
                }


                // 360浏览器
                if (this.nav.mimeTypes[30] || !this.nav.mimeTypes.length) {
                    return '360';
                }

                // chrome
                if (win.clientInformation && win.clientInformation.permissions) {
                    return 'chrome';
                }

                return '';
            },

            _testExternal: function (reg, type) {
                var external = this.win.external || {};

                for (var i in external) {
                    if (reg.test(type ? external[i] : i)) {
                        return true;
                    }
                }

                return false;
            },

            isIE: function () {
                return this.ie != null;
            },

            ieVersion: function () {
                return this.ie != null ? parseInt(this.ie[1]) : false;
            },

            isEdge: function () {
                return this.edge != null;
            },

            isSafari: function () {
                return this.safari != null;
            },

            is360: function () {
                this.chromiumType = this._getChromiumType();
                return this.chromiumType === '360';
            },

            isSogou: function () {
                this.chromiumType = this._getChromiumType();
                return this.chromiumType === 'sogou';
            },
            isChromium: function () {
                return this._getChromiumType() === 'chrome'
            },
            webglAvailable: function () {
                try {
                    var canvas = document.createElement('canvas');
                    return !!(window.WebGLRenderingContext && (
                        canvas.getContext('webgl') ||
                        canvas.getContext('experimental-webgl')));
                } catch (e) {
                    return false;
                }
            }
        },
        getBoundingClientRect: function (obj) {
            var xy = obj.getBoundingClientRect();
            var top = xy.top - document.documentElement.clientTop + document.documentElement.scrollTop, //document.documentElement.clientTop 在IE67中始终为2，其他高级点的浏览器为0
                bottom = xy.bottom,
                left = xy.left - document.documentElement.clientLeft + document.documentElement.scrollLeft, //document.documentElement.clientLeft 在IE67中始终为2，其他高级点的浏览器为0
                right = xy.right,
                width = xy.width || right - left, //IE67不存在width 使用right - left获得
                height = xy.height || bottom - top;

            return {
                top: top,
                right: right,
                bottom: bottom,
                left: left,
                width: width,
                height: height
            }
        }
    };

    var head = document.getElementsByTagName('head')[0];
    head.appendChild(AVR.createTag('meta', {
        'name': 'viewport',
        'content': "width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0,minimal-ui,user-scalable=no"
    }));
    head.appendChild(AVR.createTag('meta', {
        'name': 'google',
        'content': "notranslate"
    }));
    head.appendChild(AVR.createTag('meta', {
        'name': 'full-screen',
        'content': "yes"
    }));

    if (AVR.debug) {
        window.onerror = function (msg, url, l) {
            var txt = "There was an error on this page.\n\n";
            txt += "Error: " + msg + "\n";
            txt += "URL: " + url + "\n";
            txt += "Line: " + l + "\n\n";
            AVR.msgBox(txt, 36, document.body);
            return true;
        }
    }

    exports.VR = VR;
    exports.AR = AR;
    exports.AVR = AVR;
})));